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
Related
I am using the google cloud datastore python client to write an entity into the datastore which contains an embedded entity. An example entity might look like:
data_type: 1
raw_bytes: <unindexed blob>
values: <indexed embedded entity>
I checked the data from the console and the data is getting saved correctly and the values are present.
Next, I need to run a query from a python app engine application. I have represented the above as the following entity in my app engine code:
class DataValues(ndb.Model):
param1 = ndb.BooleanProperty()
param2 = ndb.IntegerProperty()
param3 = ndb.IntegerProperty()
class MyEntity(ndb.Expando):
data_type = ndb.IntegerProperty(required=True)
raw_bytes = ndb.BlobProperty()
values = ndb.StructuredProperty(DataValues)
One of the filters in the query depends on a property in values. Sample query code is as below:
MyEntity.query().filter(MyEntity.data_type == 1).filter(MyEntity.values.param1 == True).get()
I have created the corresponding composite index in my index.yaml
The query runs successfully but the resulting entity contains the embedded entity values as None. All other property values are present.
What can be the issue here ?
Add properties of DataValues entity as properties of the MyEntity.
This is a bit of a guess, but since datastore attributes are kind of keyed by both their name (in this case values) and the name of the "field type/class" (i.e. StructuredProperty), this might fix your problem:
class EmbeddedProperty(ndb.StructuredProperty):
pass
class MyEntity(ndb.Expando):
data_type = ndb.IntegerProperty(required=True)
raw_bytes = ndb.BlobProperty()
values = EmbeddedProperty(DataValues)
Give it a shot and let me know if values starts coming back non-null.
I struggled with the same problem, wanting to convert the embedded entity into a Python dictionary. One possible solution, although not a very elegant one, is to use a GenericProperty:
class MyEntity(ndb.Model):
data_type = ndb.IntegerProperty(required=True)
raw_bytes = ndb.BlobProperty()
values = ndb.GenericProperty()
values will then be read as an "Expando" object: Expando(param1=False,...). You can access the individual values with values.param1, values.param2 etc. I would prefer having a custom model class, but this should do the job.
I have Datastore Viewer URLs stored for specific queries such as:
SELECT * FROM User WHERE __key__ = key('User',9999)
which now, in the updated console interface, don't work. Has the syntax changed?
It appears that the key() function has been changed. It worked for me by removing the single quotes, i.e.:
SELECT * FROM User WHERE __key__ = key(User,9999)
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)
I want to write a query that does something like this SQL query:
SELECT name FROM contacts WHERE blah blah
I know I can do something like this:
for contact in Contacts.gql(WHERE_CLAUSE, args).fetch(1000):
print contact.name
but isn't there a way to get name directly from a query without having to loop on the results? would it provide any advantage in performance?
Nope. Can't be done.
A GQL query returns zero or more entities or Keys of the requested
kind. Every GQL query always begins with either SELECT * or SELECT
key. (A GQL query cannot perform a SQL-like "join" query.)
http://code.google.com/appengine/docs/python/datastore/gqlreference.html
But you can create a simple wrapper to do it for you. Something like:
def get_all_of_field(model, field):
for x in model.all():
yield getattr(x, field)
names = get_all_of_field(Contact, 'name')
Performance can't be improved that way as the entire "line" is read by the API no matter what. Either you read the entire "line" or just its key.
You can do this now using Projection queries. For db, see the documentation here:
https://developers.google.com/appengine/docs/python/datastore/projectionqueries
For ndb, see the documentation here:
https://developers.google.com/appengine/docs/python/ndb/queries#projection
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)