Converting Entity Key to urlsafe string - google-app-engine

this question is related to the new Cloud Firestore in 'Datastore Mode'.
In the old ndb datastore, it is easy to convert an Entity key into an url_safe string:
entity.key.urlsafe()
But this does not work with the new 'Database Mode'.
How can I convert an entity key to be a urlsafe string?

The (from|to)_legacy_urlsafe() methods can be used:
From entity key to urlsafe string:
my_entity_key = Key('SomeKind', 'id_123')
urlsafe_string = my_entity_key.to_legacy_urlsafe()
From urlsafe string to entity key:
from google.cloud import datastore
entity_key = datastore.Key.from_legacy_urlsafe(urlsafe_string)

Related

Autogenerated id using JPA for GAE (key as encoded String)

How to declare id field as "Key as encoded String" in JPA entity (not JDO) for usage in GAE Datastore? You can find example for JDO, but not for JPA.
Can't declare id fields as Long as entity is used in child-parent relations.
So, my entity is like this:
#Entity
public class EntityClass {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Extension(vendorName="datanucleus", key="gae.encoded-pk", value="true")
private String id;
So, it uses both JPA and JDO annotations.
So, while trying to persist entity object i'm getting an exception:
Cannot have a null primary key field if the field is unencoded and of type String. Please provide a value or, if you want the datastore to generate an id on your behalf, change the type of the field to Long.
org.datanucleus.store.appengine.FatalNucleusUserException: Invalid primary key for name.xxx.tips.db.User. Cannot have a null primary key field if the field is unencoded and of type String. Please provide a value or, if you want the datastore to generate an id on your behalf, change the type of the field to Long.
Full Stacktrace:
Cannot have a null primary key field if the field is unencoded and of type String. Please provide a value or, if you want the datastore to generate an id on your behalf, change the type of the field to Long.
org.datanucleus.store.appengine.FatalNucleusUserException: Invalid primary key for name.xxx.tips.db.User. Cannot have a null primary key field if the field is unencoded and of type String. Please provide a value or, if you want the datastore to generate an id on your behalf, change the type of the field to Long.
at org.datanucleus.store.appengine.DatastoreFieldManager.storeStringPKField(DatastoreFieldManager.java:540)
at org.datanucleus.store.appengine.DatastoreFieldManager.storeStringField(DatastoreFieldManager.java:460)
at org.datanucleus.state.AbstractStateManager.providedStringField(AbstractStateManager.java:1023)
at name.xxx.tips.db.User.jdoProvideField(User.java)
at name.xxx.tips.db.User.jdoProvideFields(User.java)
at org.datanucleus.state.JDOStateManagerImpl.provideFields(JDOStateManagerImpl.java:2715)
at org.datanucleus.store.appengine.DatastorePersistenceHandler.insertPreProcess(DatastorePersistenceHandler.java:357)
at org.datanucleus.store.appengine.DatastorePersistenceHandler.insertObjects(DatastorePersistenceHandler.java:267)
at org.datanucleus.store.appengine.DatastorePersistenceHandler.insertObject(DatastorePersistenceHandler.java:256)
at org.datanucleus.state.JDOStateManagerImpl.internalMakePersistent(JDOStateManagerImpl.java:3185)
at org.datanucleus.state.JDOStateManagerImpl.flush(JDOStateManagerImpl.java:4513)
at org.datanucleus.state.JDOStateManagerImpl.getExternalObjectId(JDOStateManagerImpl.java:1334)
at org.datanucleus.state.JDOStateManagerImpl.getObjectId(JDOStateManagerImpl.java:1234)
at name.xxx.tips.db.User.jdoGetObjectId(User.java)
at org.datanucleus.jpa.JPAAdapter.getIdForObject(JPAAdapter.java:266)
at org.datanucleus.ObjectManagerImpl.exists(ObjectManagerImpl.java:1953)
at org.datanucleus.jpa.EntityManagerImpl.refresh(EntityManagerImpl.java:469)
Why are you using JDO annotations if using JPA ?
The annotation to use for extensions with JPA is
org.datanucleus.api.jpa.annotations.Extension
as shown here
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import org.datanucleus.api.jpa.annotations.Extension;
#Entity
public class ChildEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Extension(vendorName="datanucleus", key="gae.encoded-pk", value="true")
private String Id;
This works for me.

How to search Entities effectively in google datastore

I am using Datastore low level APIs for an application (Internal job portal).
I have an entity called Candidate with following properties
Entity cadidate=new Entity("Candidate",getEmpNum());
candidate.setProperty("name","some name");
candidate.setProperty("skill","c++,Java,C#,GAE");
candiate.setProperty("empNum");
The property 'skill' takes the a comma seperated string. If an HR do a search for a candidate with a key
"GAE,Java" , how do I effectively search for entities?
will the following query works?
q.addFilter(searchBy, FilterOperator.GREATER_THAN_OR_EQUAL, searchFor);
q.addFilter(searchBy, Query.FilterOperator.LESS_THAN, searchFor+"Z");
If the above query works on say 1000 Entities ..does it work with same latency when there are 50,000 + entities in the datastore?
Please suggest me .. I am new to GAE and Datastore
-thanks
Ma
You should use list property.
List<String> skills = Arrays.asList("c++", "Java", "C#", "GAE");
candidate.setProperty("skill", skills);
then query with IN operator:
List<String> findSkills = Arrays.asList("Java","GAE");
q.addFilter("skill", FilterOperator.IN, findSkills);
This

Incorrect Key in Datastore

Write to datastore
Key dataKey = KeyFactory.createKey("Datastore", "123");
DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
Entity data = new Entity("Datastore", dataKey);
data.setProperty("date", date);
try{
datastore.get(dataKey);
datastore.delete(dataKey);
}catch(EntityNotFoundException ex){
log.serve("Error : "+ ex.getMessage());
}
datastore.put(data);
Read from datastore
Key dataKey = KeyFactory.createKey("Datastore", "123");
DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
Entity entity = datastore.get(dataKey);
I have 02 questions:
1. I use datastore.get(dataKey) to check whether the entity is existed or not, because I want to avoid duplicated entity with same key but I don't think the way i'm using is good. Is there any other way can do it better?
2. I can't get data back. It said that " No entity was found matching the key: Datastore("123")"
I read google datastore documentation again and again but I still can't find out what wrong with this :(.
Can somebody help me please ?
Thank you.
Replace:
Entity data = new Entity("Datastore", dataKey)
with:
Entity data = new Entity(dataKey)
Also you don't need to worry about duplicates, if you commit an existing entry (which its key is already in the datastore) it will be override. There can't be two same keys in the datastore.

Google App Engine - Adding a record only if it doesn't exist yet

In Google App Engine, consider the following datastore model:
class Update(db.Model):
content = db.TextProperty()
date = db.DateTimeProperty()
source = db.StringProperty()
To add a new record, I do something like:
db.put(Update(content=..., date=..., source=...))
How can I add a record to the datastore only if it doesn't exist yet? What is the most efficient way to do this?
db.Model.get_or_insert(key_name) lets you pass the key name of the object to get or insert (think of it like a primary key)
More information about key_name

unique constraints-Google app engine [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Unique Constraint At Data Level in GAE
Does the Google App engine datastore support unique constraints?
Not really, but keys are guaranteed to be unique and you can set the key of your entity to be an arbitrary string. You can take advantage of this to create a unique key when you save your entity to the data store. For example,
public class Entity implements Serializable {
#Id String id;
String unique_together_1;
String unique_together_2;
public Entity (String unique_together_1, String unique_together_2) {
this.id = unique_together_1 + "-" + unique_together_2;
this.unique_together_1 = unique_together_1;
this.unique_together_2 = unique_together_2;
}
Obviously this won't work if the unique fields of your entity change later or if you need multiple unique constraints for a single entity type.

Resources