Why does Google AppEngine have two primary keys, 'key' and 'id/name'? - google-app-engine

If you leave one or the other empty, or don't specify in your Entity, it creates a key/id for that entity anyways, as seen in the admin console datastore viewer.
Bonus question: Why can't you get the ID for an Entity object after you put() it? entity.getProperty("id") returns null. Key objects cannot be serialized so cannot be used by GWT.
Reference:
https://developers.google.com/appengine/docs/java/datastore/entities
https://developers.google.com/appengine/docs/java/datastore/jdo/creatinggettinganddeletingdata#Keys

Entities have a Key, and Keys (of persisted entities) have either auto-assigned ids, or programmer-supplied names. The name/id is a property of the Key, not a property of the Entity.
Instead of entity.getProperty("id") in Java you write entity.getKey().getId() (or .getName() if you gave the key a name).
The lower-level details are in:
https://developers.google.com/appengine/docs/java/javadoc/com/google/appengine/api/datastore/Entity
https://developers.google.com/appengine/docs/java/javadoc/com/google/appengine/api/datastore/Key
`

Related

Key vs ID/Name?

I do not want to create an autogenerated key for my entities so I specify my own:
Entity employee = Entity.newBuilder().setKey(makeKey("Employee", "bobby"))
.addProperty(makeProperty("fname", makeValue("fname").setIndexed(false)))
.addProperty(makeProperty("lname", makeValue("lname").setIndexed(false)))
.build();
CommitRequest request = CommitRequest.newBuilder()
.setMode(CommitRequest.Mode.NON_TRANSACTIONAL)
.setMutation(Mutation.newBuilder().addInsert(employee))
.build();
datastore.commit(request);
When I check to see what the entity looks like it looks like this:
Why is this auto-generated key generated if I specified my own key (bobby)? It seems bobby was also created, but now I have bobby and this autogenerated key. What is the difference between the key and id/name?
You can't specify your own key, keys actually contain information necessary for the datastore operation. This note in the documentation gives you an idea:
Note: The URL-safe string looks cryptic, but it is not encrypted! It
can easily be decoded to recover the original entity's kind and
identifier:
key = Key(urlsafe=url_string)
kind_string = key.kind()
ident = key.id()
If you use such URL-safe keys, don't use sensitive data such as email
addresses as entity identifiers. (A possible solution would be to use
the MD5 hash of the sensitive data as the identifier. This stops third
parties, who can see the encrypted keys, from using them to harvest
email addresses, though it doesn't stop them from independently
generating their own hash of a known email address and using it to
check whether that address is present in the Datastore.)
What you can specify is the ID portion of the key, either as a number or as a string:
A key is a series of kind-ID pairs. You want to make sure each entity
has a key that is unique within its application and namespace. An
application can create an entity without specifying an ID; the
Datastore automatically generates a numeric ID. If an application
picks some IDs "by hand" and they're numeric and the application lets
the Datastore generate some IDs automatically, the Datastore might
choose some IDs that the application already used. To avoid, this, the
application should "reserve" the range of numbers it will use to
choose IDs (or use string IDs to avoid this issue entirely).
This is the url-safe version of your key, suitable for use in links. Use KeyFactory.stringToKey to convert it to an actual key, and you'll see that it contains your string name.
What you create with makeKey("Employee", "bobby") is a key for an Entity with the entity name Employee and the name bobby. What you see as Key in the datastore viewer is a representation for exactly that.
Generally speaking a key always consists of
optional parent key (with entity type and name/id)
entity type
entity name/id
Maybe someone here can tell you how to decode the key into its components but rest asured that you're doing everything right and the behavior is as expected.

get the entity via key string , google app engine ndb(datastore)

I am using google app engine with python. the server got the entity key from the user, then I use this code to bring the entity:
key.get()
but I also want to get the entity just if it related to particular model, How could I do that ?
I know that I could do that by this code:
MyModel.get_by_id('my_key')
but this works just for the key_name and the id , and in my case I use the key ?
After getting user-provided key as urlsafe string from server, construct the NDB key, e.g.:
key = ndb.Key(urlsafe=string)
I'm not sure though, why you don't simply use key.get() after importing MyModel :-)
However, this is how you get an instance using its ID (whether string or integer):
MyModel.get_by_id(key.id(), parent=key.parent(), app=key.app(), namespace=key.namespace())
The keywords are optional, unless you use multiple namespaces or application IDs, or MyModel is child class in an entity group.
Alternatively, use key.string_id() or key.integer_id()
Security warning: Since your app accepts user-provided keys, be aware that even the cryptically looking URL-safe keys can be easily encoded/decoded.
For details see Reference for NDB Key

Selecting Entity based on auto generated ID in google datastore

I have created an entity with few attributes but without specifying any key in which case an auto generated ID has been created in data-store.
Entity en=new Entity("Job");
Now when I fetch such entities and try to store it in Java object, how can I get the auto generated ID (which I required to perform UPDATE operation later)?
I have tried the below ways but it does not return Identifier value.
en.getProperty("__key__");
en.getProperty("ID/Name");
en.getProperty("Key");
You are probably looking for:
en.getProperty(Entity.KEY_RESERVED_PROPERTY)
mentioned in Key Filters (not an obvious place to find it).
Another approach would be to try:
en.getKey().getId()
mentioned in Entity JavaDoc and Key JavaDoc.

Filter by key in App Engine datastore in Java

You would think that this would be an easy question to answer.
How do I, in Java, filter by an entity's key (not a property that just happens to be of type Key, but its actual key - what we would call the "primary key" in relational database land)?
I don't want to get a single entity with a particular key. I actually do want to do a filter and return a subset of the entities.
The trick is to use Entity.KEY_RESERVED_PROPERTY in place of property name:
Query q = new Query("MyEntity");
q.setFilter(new Query.FilterPredicate(Entity.KEY_RESERVED_PROPERTY,
Query.FilterOperator.GREATER_THAN,
KeyFactory.createKey("MyEntity", "somevalue")));
This will find all MyEntity entities with key greater than somevalue.

How to change Keys of entities from Long to String in Google AppEngine Datastore?

I have many entities of one type which have Key with auto-generated Long ID (e.g. Person(1234)), but now I need to change those keys to have String name instead (e.g. Person("username")).
How should I achieve this?
You have two options:
Add a username attribute to the entity and get (using query) the entity by user name.
When creating the Person entity provide a key_name (Person(key_name=username, ...) ), but you will need to migrate all the existing Person entities by recreating them.
Once an entity has been saved to the datastore, it's key cannot be changed. So you'll either have to make do with the existing keys, or create new entities with the new keys and remap any existing pointers to the original entities.

Resources