Reputation: 5313
When I save an entity to the datastore with a numeric key:
datastore.save({
key: datastore.key(['Thing', 123]),
data: [
{ name: 'name', value: 'My thing' }
]
});
And then retrieve it again
datastore
.createQuery('Thing')
.filter('__key__', datastore.key(['Thing', 123]))
.select('__key__')
.run((err, entities) => {
const key = entities[0][datastore.KEY];
console.log(`key.id = ${key.id}, type = ${typeof key.id}`);
});
This outputs:
key.id = 123, type = string
But I'd expect it to output:
key.id = 123, type = number
The datastore library seems to go through great lengths to ensure that the ID is a number, but then proceeds to return it as as string. When using the ID to create a new key, e.g.
const newKey = datastore.key(['Thing', key.id]);
This returns a key that will be unable to find any entities, because the value will be assigned to the name
instead of the id
because it's a string.
I've made a small repro case here: https://github.com/arjenvanderende/datastore-key-id-is-string
It seems very strange to me that the ID is returned as a string instead of a number. Is this expected behaviour or is this a bug in the library?
This issue becomes a bigger problem when you have a "foreign key" to another object and you use key.id
to set it. E.g.
datastore.save({
key: datastore.key(['Thing', 234]),
data: [
{ name: 'name', value: 'My other thing' }
{ name: 'parentThingId', value: thing[datastore.KEY].id }
]
});
After retrieving this object again from the datastore, looking up the parent of the other thing will fail. Doing a lookup in the datastore with the key datastore.key(['Thing', otherThing.parentThingId)
will yield no results, because it tries to lookup it up by name
instead of id
. It isn't immediately apparent that this is the issue, because types are somewhat hidden in the datastore console.
Upvotes: 1
Views: 2644
Reputation: 5770
It is a string, but it is recognized as an id
. The API does the proper thing when you make future requests with the key
object.
We have to do some special-case handling in the library, because IDs can be very long-- beyond the allowable ceiling for a JavaScript integer. Our storing it as a string is an internal artifact that should not affect the user.
When using the ID to create a new key, e.g.
const newKey = datastore.key(['Thing', key.id]);
Why not just use key
itself instead of creating a new Key object?
Alternatively, you can force the ID type by using:
const newKey = datastore.key(['Thing', datastore.int(key.id)]);
Upvotes: 4