2

I have a datastore transaction where I create an entity (a user) letting datastore generate the ID for me.

I then would like to use that ID so that I can create another entity (of another kind).

While this is possible with regular datastore 'save' api:

datastore.save(user).then(() => {
  userId = user.key.id // returns entity's ID created by datastore
})

However, this does not seem possible when using a transaction:

transaction.save(user).then(() => {
  console.log( user.key.id )
})

The above outputs "cannot read 'then' of undefined'", even though there's no callback listed in the docs, i tried anyway.

When creating/saving an entity with a transaction, how can I retrieve that entity's autogenerated ID?

sqram
  • 7,069
  • 8
  • 48
  • 66
  • 1
    I have not experience with node.js and the datastore but I faced a similar problem with objectify (java). When I called ...save() I could not read the autogenerated id, I had to call ...save().now(). It seems to be that some entities are save in async mode. Maybe you can check if a similar possibility exists to save the entities – Michael Meyer Apr 13 '17 at 06:40

1 Answers1

3

Allocate IDs

You can use Method: projects.allocateIds before entering the transaction:

Allocates IDs for the given keys, which is useful for referencing an entity before it is inserted.

Using the Python client library.

This will make Datastore 'reserve' IDs (even though there still won't be any entities created with those IDs) and avoid ID collision before inserting.

Inside your transaction, you get one ID from those allocated and assign to the first entity. Then you can reference the same ID in your second entity, even before the transaction committed the first entity insert.

Best practice for transactions

Transactions have a maximum duration of 60 seconds with a 10 second idle expiration time after 30 seconds.

Because of that, the best practice is performing everything possible before entering your transaction. Allocate IDs is, of course, one of the things you can run before your transaction.

Renato Byrro
  • 3,578
  • 19
  • 34
  • 1
    Thanks. allocateIds was the trick. Using koa2, I had to do `const userKey = datastore.key(['User']); const allocatedUser = await transaction.allocateIds(userKey, 1); const userId = allocatedUser[0][0].id`, then when creating the entity: `const user = { key: datastore.key(['User', userId]),` – sqram Apr 13 '17 at 15:24