Using entity key to retrieve entries from datastore - google-app-engine

My Datastore contains: an entry with an id/Name id = 30001
I tried: SELECT * FROM Skill WHERE Id=30001 and a few other variations.
How can i use the entity key to retrieve entries?

The fastest and more convenient method to retrieve a Model by a given id is by calling the get_by_id() class method of the Model:
skill = Skill.get_by_id(30001)
Using GQL is pretty much slower and it's achieved using KEY:
SELECT * FROM Skill WHERE __key__ = KEY('Skill',30001)

Related

reduce google datastore read operation fee

I have a Kind XXX_account with 1000 entities. The Kind file size is 3 mb. Whenever I send a request, the Query need to be called to find a certain entity in the Kind. Therefore, I think the google fee is almost 4 usd in just a 20 hours.
Is there anyway to reduce the datastore read operations? I plan to store 1000 entities in txt file so that I do need to read datastore everytime.
Datastore Read Operations 5.01 Million Ops 4.96 $0.70/ Million Ops $3.48
My model.py
class MyUser(DatastoreUser):
pass
class XXXAccount(db.Model):
user = db.ReferenceProperty(MyUser,
collection_name='xxx_accounts')
id = db.StringProperty(required=True)
created = db.DateTimeProperty(auto_now_add=True)
updated = db.DateTimeProperty(auto_now=True)
name = db.StringProperty(required=True)
username = db.StringProperty(required=True)
profile_url = db.StringProperty(required=True)
aaa = db.StringProperty(required=True)
bbb = db.StringProperty(required=True)
view.py
#login_required
def updateprofile(request):
number_form = NumberForm()
if request.method =="POST" and number_form.validate(request.form):
acc_num_str = number_form['nb']
acc_num = int(acc_num_str)
current_user = request.user
xxx_account = current_user.xxx_accounts[acc_num] #Query
DO SOME THING WHICH DOES NOT RELATED TO READ AND WRITE DATASTORE OPERATION
return......
UPDATE:
Code was posted
OMG, 0.32 USD for just 1000 requests.
You should post your model definition and code where you do querying entities.
Common recommendations:
If you want to find certain entity(ies), there is only one right way to do it - use entity key (id number or key_name string) to get it. Datastore automatically assigns some id to entity when it saves it or you can manually set some nice key_name when you're creating entity.
To get entity's id or key_name use Model.key().id() or Model.key().name() in DB or Model.key.id() in NDB.
Then you can get entity by id or key_name with Model.get_by_id() or Model.get_by_key_name() methods if you're using old DB API or Key.get() method if you're using new NDB API. You can pass id or key_name to URL - http://example.com/getentity/[id].
Also, use Memcache to cache entities. Caching can extremely decrease using of Datastore. By the way, NDB automatically uses cache.
p.s. Sorry, I cannot post more than 2 links.

Can I query by document id with full text search on App Engine?

After creating a document with a explicit id like this:
Document(doc_id = 123)
Is it possible to find that document using the id, similar to get_by_id with the Datastore?
I've tried queries with id:123, _id:123, doc_id:123, and _doc_id:123.
Index.list_documents has the options start_doc_id and limit which can be used to get a single document by id.
documents = index.list_documents(start_doc_id = id, limit = 1)
I also found in Java that you can do index.get(ID), which might be useful for Java users.
Here's the Javadoc:
https://developers.google.com/appengine/docs/java/javadoc/com/google/appengine/api/search/Index#get(java.lang.String)

What is the compatible version of this query for NDB?

Maybe it's wrong but I always use this query for my app:
cme_only = Comput.all().filter('__key__ =', cid.key())
What is the compatible version of this query for NDB?
The Metadata queries are very different..
edit:
cid is an entity and cme_only is an iterable that I'm sure has only one value
cid = Comput.get_by_id(int(self.request.get('id')))
cme_only = Comput.all().filter('__key__ =', cid.key())
and then in template:
{{ for Comput in cme_only }}
I do not like it but it was enough
There's no need for metadata queries. The NDB way to spell a query on __key__ is as follows:
ModelClass.query(ModelClass._key == key_value)
That is, just like querying for property foo is done by filtering on ModelClass.foo == value, ModelClass._key is a pseudo-property representing the key.
The other posters are correct that if you just one a single entity given its full key, using the get() method on the Key object is better (faster and cheaper). Also, if e is an entity (model instance), in NDB, the key is not e.key() but e.key (or e._key -- yes, that's the same _key attribute I mentioned in above, it works as a class attribute and as an instance attribute).
And indeed, if you have a urlsafe key (e.g. 'agFfcg4LEghFbXBsb3llZRgDDA') the way to turn it into a Key object is ndb.Key(urlsafe='agFfcg4LEghFbXBsb3llZRgDDA').
Good luck!
If cid is your entity then you could do that:
from google.appengine.ext import ndb
cme_only = ndb.Key(Comput, cid.key.id()).get()
But this will return you basically the same entity that you start with, the cid, But in general this is one way of querying by key.
You can check more on how to construct keys in the docs.

GQL query with numeric id in datastore viewer

I want to build GQL query to get an object using its numeric id. I'm doing this in Datastore viewer in App management console, so I can't use Model.get_by_id(numeric_id). Something like
SELECT * FROM Model WHERE id = <numeric_id>
also doesn't work.
Try this:
SELECT * FROM Model where __key__ = KEY('Model', <numeric_id>)
Unfortunately, there does not appear to be a way to write a query equivalent to
SELECT * FROM Model WHERE id = <numeric_id>
which would select all Model entities with the given id. If you're ok with something equivalent to
SELECT * FROM Model WHERE id = <numeric_id> AND parent IS NULL
you can use something like
SELECT * FROM Model where __key__ = KEY('Model', <numeric_id>)
If your entity does have a parent though, you'll need to specify that as part of the key, like
SELECT * FROM Model where __key__ = KEY('ParentModel', <parent_name_or_id>, 'Model', <numeric_id>)
If the parent itself has a parent, you'll need to specify that too. (Grandparent goes left of the parent, and so on.)
Of course if you're not restricted to GQL (like if you're using Python, Go, or Java), you can query the keys, decode them and filter by id, then fetch the corresponding entities. But of course that doesn't work in the Datastore Viewer since you can only use GQL.
Another way around is, first get the key for the entity using the id by
key = db.Key.from_path('Model', int(id))
then get the object by
obj = db.get(key)
The advantage is, you do not have to do any string formatting.
reference: problem set 3 at this course, https://classroom.udacity.com/courses/cs253/
I was getting this error:
GQL Query error: Encountered ... at line 1, column 42. Was expecting
one of: UNQUOTED_NAME ... QUOTED_NAME ..."
It turns out that in the Google AppEngine datastore developer's admin console, you should drop the quotes and use something like this:
SELECT * FROM MyEntity WHERE __key__ = Key(MyEntity, 5695872079757312)
In my case I had to change the type of ID from String to Long

Google App Engine Query (not filter) for children of an entity

Are the children of an entity available in a Query?
Given:
class Factory(db.Model):
""" Parent-kind """
name = db.StringProperty()
class Product(db.Model):
""" Child kind, use Product(parent=factory) to make """
#property
def factory(self):
return self.parent()
serial = db.IntegerProperty()
Assume 500 factories have made 500 products for a total of 250,000 products. Is there a way to form a resource-efficient query that will return just the 500 products made by one particular factory? The ancestor method is a filter, so using e.g. Product.all().ancestor(factory_1) would require repeated calls to the datastore.
Although ancestor is described as a "filter", it actually just updates the query to add the ancestor condition. You don't send a request to the datastore until you iterate over the query, so what you have will work fine.
One minor point though: 500 entities with the same parent can hurt scalability, since writes are serialized to members of an entity group. If you just want to track the factory that made a product, use a ReferenceProperty:
class Product(db.Model):
factory = db.ReferenceProperty(Factory, collection_name="products")
You can then get all the products by using:
myFactory.products

Resources