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

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

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.

Google App Engine about key in ndb

I am new in web development and also in google app engine. I dont really understand what the function of key in ndb, i think it is like a primary key for each row? If the function of key is to identified any rows in each entities, can I use it to do the query?
I also do not understand how to retrieve the key in each rows. In the docs we should use this code to return key, and also store to database.
sandy_key = sandy.put()
What if i do not want to store anything but i only want to retrieve the key. For example:
class Post(ndb.Model):
title = ndb.StringProperty()
content = ndb.TextProperty()
created = ndb.DateTimeProperty(auto_now=True)
And then I do a query.
q = Post.query(Post.title == "test")
Is it possible to get the key from that query?
Thank you
You are actually looking for the entity's id (or identifier). An entity's key is made up of an identifier and a kind. The kind is typically the name of the Model, which in your case is "Post".
You can retrieve an entity's id using the .id() method. In your example, you must first "fetch" or "get" an entity. You provided a query. If you were to fetch one entity matching your query and find the id of that entity, your code would look like this:
q = Post.query(Post.title == "test")
my_entity = q.fetch(1, keys_only=True)
my_key = my_entity.id()
The "keys_only" parameter in the fetch is not necessary, but it does save resources because it tells the fetch to only retrieve the key.
This information is explained in the NDB Entity Keys documentation.

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.

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

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
`

Issues understanding Google App Engine key

I'm looking at the GAE example for datastoring here, and among other things this confused me a bit.
def guestbook_key(guestbook_name=DEFAULT_GUESTBOOK_NAME):
"""Constructs a Datastore key for a Guestbook entity with guestbook_name."""
return ndb.Key('Guestbook', guestbook_name)
I understand why we need the key, but why is 'Guestbook' necessary? Is it so you can query for all 'Guestbook' objects in the datastore? But if you need to search a datastore for a type of object why isn't there a query(type(Greeting)? Concidering that that is the ndb.model that you are putting in?
Additionally, if you are feeling generous, why in creating the object you are storing, do you have to set parent?
greeting = Greeting(parent=guestbook_key(guestbook_name))
First: GAE Datastore is one big distributed database used by all GAE apps concurrently. To distinguish entities GAE uses system-wide keys. A key is composed of:
Your application name (implicitly set, not visible via API)
Namespace, set via Namespace API (if not set in code, then an empty namespace is used).
Kind of entity. This is just a string and has nothing to do with types at database level. Datastore is schema-less so there are no types. However, language based APIs (Java JDO/JPA/objectify, Python NDB) map this to classes/objects.
Parent keys (afaik, serialised inside key). This is used to establish entity groups (defining scope of transactions).
A particular entity identifier: name (string) or ID (long). They are unique within namespace and kind (and parent key if defined) - see this for more info on ID uniqueness.
See Key methods (java) to see what data is actually stored within the key.
Second: It seems that GAE Python API does not allow you to query Datastore without defining classes that map to entity kind (I don't use GAE Python, so I might be wrong). Java does have a low-level API that you can use without mapping to classes.
Third: You are not required to define a parent to an entity. Defining a parent is a way to define entity groups, which are important when using transactions. See ancestor paths and
transactions.
That's what a key is: a path consisting of pairs of kind and ID. The key is what identifies what kind it is.
I don't understand your second question. You don't have to set a parent, but if you want to set one, you can only do it when creating the entity.

Resources