How to retrieve entity from key value in GQL - google-app-engine

I am using Google App Engine's datastore and wants to retrieve an entity whose key value is written as
ID/Name
id=1
Can anyone suggest me a GQL query to view that entity in datastore admin console and also in my python program?

From your application use the get_by_id() class method of the Model:
entity = YourModel.get_by_id(1)
From Datastore viewer you should use the KEY function:
SELECT * FROM YourModel WHERE __key__ = KEY('YourModel',1)

An application can retrieve a model instance for a given Key using the get() function.
class member(db.Model):
firstName=db.StringProperty(verbose_name='First Name',required=False)
lastName=db.StringProperty(verbose_name='Last Name',required=False)
...
id = int(self.request.get('id'))
entity= member.get(db.Key.from_path('member', id))
I'm not sure how to return a specific entity in the admin console.

Related

How to get related to db.Model entity from datastore - what API allows it?

I want to read related to model entity. What API I should use?
For example:
class DeleteMe(db.Model):
x = db.FloatProperty()
DeleteMe(key_name = '1').put()
How to read raw entity from datastore for key_name = '1'?
To get the corresponding model that you just put, use get_by_key_name. (https://developers.google.com/appengine/docs/python/datastore/modelclass#Model_get_by_key_name)
DeleteMe.get_by_key_name('1')
However, I noticed you're using the db package and not ndb. I would encourage you to use ndb as it has many optimizations and a more powerful API to the datastore.
https://developers.google.com/appengine/docs/python/ndb/
Corresponding code for NDB might look like:
from google.appengine.ext import ndb
class DeleteMe(ndb.Model):
x = ndb.FloatProperty()
DeleteMe(id='1').put()
DeleteMe.get_by_id('1')

Add field to App Engine-hosted database

I'm currently developing a mobile application who uses a Google App Engine-hosted web service.
But i'm facing an issue. I just want to add a field in one my database's table.
App Engine doesn't use classic SQL syntax, but GQL. So i cannot use the ALTER TABLE statement. How can i do this with GQL ? I looked for a solution on the web, but there's not a lot of help.
public MyEntity() {
}
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Key idStation;
private String name;
private double longitude;
private double latitude;
private java.util.Date dateRefresh = new Date(); //the field i want to add in DB
So, now when i create a "MyEntity" object, it should add the "dateRefresh" field into the database... I create my object like this:
MyEntity station = new MyEntity();
station.setName("test");
station.setLatitude(0);
station.setLongitude(0);
station.setDateRefresh(new Date("01/01/1980"));
DaoFactory.getStationDao().addStation(station);
addStation method:
#Override
public MyEntity addStation(MyEntity station) {
EntityManager em = PersistenceManager.getEntityManagerFactory().createEntityManager();
try {
em.getTransaction().begin();
em.persist(station);
em.getTransaction().commit();
} finally {
if(em.getTransaction().isActive()) em.getTransaction().rollback();
em.close();
}
return station;
}
The field "dateRefresh" is never created into my DB...
Someone to help me please ?
Thanks in advance
Just add another field to your data structure, maybe providing a default clause, and that's all. For example, if you have a UserAccount:
class UserAccount(db.Model):
user = db.UserProperty()
user_id = db.StringProperty()
you may easily add:
class UserAccount(db.Model):
user = db.UserProperty()
user_id = db.StringProperty()
extra_info = db.IntegerProperty(default=0)
timezone = db.StringProperty(default="UTC")
and let it go.
While the datastore kinda mimics tables, data is stored on a per entity basis. There is no schema or table.
All you need to do is update your model class, and new entities will be saved with the structure (fields) of the new entity.
Old entities and indexes, however, are not automatically updated. They still have the same fields as they had when they were originally written to the datastore.
There's two ways to do this. One is to make sure your code can handle situations where your new properties are missing, ie make sure no exceptions are thrown, or handle the exceptions properly when you're missing the properties.
The second way is to write a little function (usu a mapreduce function) to update every entity with appropriate or null values for your new properties.
Note that indexes are not updated unless the entity is written. So if you add a new indexed property, old entities won't show up when you query for the new property. In this case, you must use the second method and update all the entities in the datastore so that they are indexed.

Queries with Objectify: UmbrellaException

I am using Objectify to manage GAE Datastore for my GWT app. The problem is that I am not using queries properly and I get UmbrellaExceptions as per below:
Caused by: java.lang.RuntimeException: Server Error: java.lang.String cannot be cast to java.lang.Number
at com.google.web.bindery.requestfactory.shared.Receiver.onFailure(Receiver.java:44)
Say that I have a class Box with a unique field String id. I want to get the Box object whose id == "cHVQP6zZiUjM"
This is how I do it now:
public Box getBox(String boxId)
{
Objectify ofy = ObjectifyService.begin();
Query<Box> q=ofy.query(Box.class).filter("id",boxId);
Box targetBox = q.get();
return targetBox;
}
#Entity
public class Box extends DatastoreObject{
private String id;
private String title;
}
I tried doing this with ofy.load() but that method is not defined in my class Objectify (I don't know why).
Your key is encoded. Try using:
Box targetBox = ofy.get(Box.class, KeyFactory.stringToKey(boxId));
To decode your key.
The short answer: You are missing the #Id annotation in your entity.
The long answer: Id fields are special in the datastore. The id is not a real property, but rather a part of the Key that identifies the entity. You can't really filter on id fields, but you can filter on a special field called __key__. Objectify is somewhat clever about letting you filter by the id field and converting this to a __key__ filter under the covers, but it can't do it if you don't annotate the entity properly!
Actually I'm a little confused because Objectify shouldn't let you register the entity without an #Id field.
By the way, there are two sections of the documentation: Objectify4 (release coming soon) and Objectify3. Since you're using Ofy3, there is no load() method.
Another thing: Get-by-key operations are strongly preferred to queries when the operations are equivalent (as they are in your example).

Google App Engine ndb equivalent for modelname_set (backreference property)

Is there an equivalent for modelname_set (a back-referenced property) in Google App Engine's NDB?
In the old DB a Model entity had described the back-reference property as:
The name of the back-reference property defaults to modelname_set (with the name of the model class in lowercase letters, and "_set" added to the end), and can be adjusted using the collection_name argument to the ReferenceProperty constructor.
I noticed this property does not seem to exist with NDB db.Model instances.
Does NDB have an equivalent to the back-reference property?
There is no direct back-reference properties in NDB because NDB doesn't quite use the same paradigm as the original datastore client. You would use a KeyProperty for your forward reference and then use a query for everything that has that KeyProperty set for your back reference.
class Comment(ndb.Model)
source = ndb.KeyProperty()
qry = Comment.query().filter(source=ndb.Key('Source', 'Sandy'))

GQL query for <missing>

When you change data models on the app engine to add new properties those entries without a certain property are listed with the value <missing> in the online data viewer.
What I'm wondering is how can I write a query to find those entries?
There is no direct way to query for older entities with missing attribute, but you can design data model upfront to support this. Add a version attribute to each model class. Version should have a default value, which is increased every time model class is changed and deployed. This way you will be able to query entities by version number.
There's no way to query the datastore for entities that don't have a given property. You need to iterate over all the entities and check each one - possibly by using the mapreduce API.
Or you could create a script to stick null in there for all current items that don't have that property using the low level datastore API, so then you can query on null.
I had this issue and that's how I solved it. The rough code would look like:
DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
Query query = new Query("JDOObjectType");
List<Entity> results = datastore.prepare(query).asList(FetchOptions.Builder.withLimit(9999));
for (Entity lObject : results) {
Object lProperty = lObject.getProperty("YOUR_PROPERTY");
if (lProperty == null) {
lObject.setProperty("YOUR_PROPERTY", null);
datastore.put(lProperty);
}
}
}

Resources