I'm using JDO with Google App Engine for storage and I'm wondering what is the difference between the Key object and Long for id?
I find the long ID more practical, am I missing anything?
Thanks.
A Key is globally uniquely identifier which uniques identifies an entity across all of app engine. It consists of two pieces:
A path describing what app the entity belongs to, any ancestor keys, and the entity's kind.
An ID (a long) or a key name (a string).
Regardless of whether you choose to use a long or a string as the second piece, there is a Key object is associated with every entity stored in the datastore.
Related
I've got a simple question about datastore keys. If I delete an entity, is there any possibility that the key will be created again? or each key is unique and can be generated only one-time?
Thanks.
It is definitely possible to re-use keys.
Easy to test, for example using the datastore admin page:
create an entity for one of your entity models using a custom/specified key name and some property values
delete the entity
create another one using the same key name and different property values...
As for the keys with auto-generated IDs it is theoretically possible, but I guess rather unlikely due to the high number of possibilities. From Assigning identifiers:
Cloud Datastore can be configured to generate auto IDs using two
different auto id policies:
The default policy generates a random sequence of unused IDs that are approximately uniformly distributed. Each ID can be up to 16
decimal digits long.
The legacy policy creates a sequence of non-consecutive smaller integer IDs.
I am creating string datastore IDs for entity "A" from auto-generated IDs of entity "B." Should I prefix the A ID with "A-PREFIX"-B.IntID() or go with B.IntID()+"A-PREFIX?"
I assume I should start with the B ID because they are uniformly distributed so as to prevent hotspots?
From https://cloud.google.com/developers/articles/balancing-strong-and-eventual-consistency-with-google-cloud-datastore
Anti-Pattern #1: Sequential Numbering of Entity Keys
Thanks,
Andrew
You do not need any prefix at all. A key consists of an entity kind and an ID. So two entities may have the same ID and still have unique keys if they belong to different kinds.
This example works perfectly fine (example in Java):
Entity userEntity = new Entity("User");
Long id = datastore.put(userEntity).getId();
Entity loginEntity = new Entity("Login", id);
datastore.put(loginEntity);
Note that if you take a Long id and convert it into a String, your keys will take up much more space. So using a Long for an id is a better option.
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
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.
In Google appengine datastore, Is it possible to define both id and key_name for one entry?
The documantation of Key.from_path says that only can define id or key_name for it, so which means that an entry can has id or key_name, right?
No. You can one or the other, but not both.
See http://code.google.com/appengine/docs/python/datastore/entities.html#Kinds_IDs_and_Names
The entity ID is part of the key. This can be an arbirary string specified by the app, or it can be generated automatically by the datastore. The API calls an entity ID given by the app a key name, and an entity ID generated by the datastore an ID. An entity has either a key name or an ID, but not both. The ID is populated when the entity object is saved to the datastore for the first time.