Google App Engine about key in ndb - google-app-engine

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.

Related

Compound Key Performance For App Engine Datastore

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.

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

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.

Get all of the instance names from a many to many object?

I tried querying the Db with this bit of code:
Makesite.objects.values_list('ref_id', flat =True)
and it returned [1,2,None]. Which I found to be moderately confusing. I assumed that python saved the instances by their own names and not numbers that it just assigns to them. Any help with the code or an explanation to why python saves them as numbers and not their names would be awesome thanks.
In models.py
class Makesite(models.Model):
sitename = models.CharField(max_length=100, unique = True)
siteinfo = models.ManyToManyField(Siteinfo)
ref_id = models.ManyToManyField(RefID)
report = models.ManyToManyField(Report)
Django doesn't save m2m by their "names". It uses their primary keys (in your case - integers). You can check it, by viewing your DB tables.
When you just use something like makesite.sitename Django makes anither query to fetch sitename instance.
But when you use values_list you don't want extra queries or joins, that's why Django returns data from a single table. And all that it can get form there is a primary key.
If you want to optimize your related queries take a look at select_related / prefetch_related methods or use caching.

Is there any way to have key_name and id at the same time for GAE datastore entity?

In addition to the key_name I generate, I also would like to have some other property, which will act as id (I don't want to show key_name to the user). Can it be id? Or, how to generate unique value instead of id?
What I will do - I will generate a url with usage of that id and parent key name. If user clicks on this link, I'll need to find this datastore entity and update it.
Here is the current code.
Creation of the record:
item = Items.get_by_key_name(key_names=user_id, parent=person)
if item is None:
item = Items(key_name='id'+user_id, parent=person)
Getting the record:
item = Items.get_by_key_name(key_names=user_id, parent=person)
user_id is what should be hidden.
I could be probably wrong because your requirements are not clear, but for me you should pass just the key to the view using:
item.key()
then you could pass back the key to the controller and easily retrieve a given entity with:
item = Items.get(key)
Entities have exactly one of a key name or ID - never both. You could create an entity with a single ReferenceProperty pointing to your target entity, and use its ID as an identifier, but there really should be no reason not to reveal a key name to a user - a well authored app should not rely on this value remaining secret.
Note that it's trivially easy to extract the key name (and the rest of the information about a key) from the string encoded key.

Resources