I am stuck with geting a persisted object by its id. I am getting an error:
com.google.appengine.api.datastore.EntityNotFoundException: No entity was found matching the key: CNG("T78")
I persist the object as below to the data store:
Key cngKey = KeyFactory.createKey("CNG", jsonCNG.cNGID);
Entity cngEntity = new Entity("CNG", cngKey);
cngEntity.setProperty("cng_name", jsonCNG.cNGName);
cngEntity.setProperty("cng_type", jsonCNG.cNGType);
cngEntity.setProperty("cng_content", cng);
Here cng is a json string. I set the key with a string: cNGID. I am trying to use the same id to get the object.
Key cngKey = KeyFactory.createKey("CNG", "T78")
and end up getting the above error.
The constructor new Entity("CNG", cngKey) is defining the entity with kind and parent key. Then when you try to retrieve it you do not provide parent key: KeyFactory.createKey("CNG", "T78"). This does not work - you must either provide parent key in both places on not.
Note - defining entity parent is used when defining entity groups, which are in turn important when using transactions. You probably did not want that?
Instead you should just use new Entity(cngKey).
You don't seem to have saved it to the datastore.
Datastore.put(cngEntity);
Related
Is a key value mandatory while setting up an EntityType?
This may sound a little odd but I have a case where a key is unnecessary. So I was asking myself if I can get rid of these code lines.
List<PropertyRef> keyProperties = new ArrayList<PropertyRef>();
keyProperties.add(new PropertyRef().setName("KEY"));
Key key = new Key().setKeys(keyProperties);
A key is required for an entityType in olingo and odata, because if there is no unique key for an entity then we won't be able to use getEntity (to query the data of just one entity from a given entitySet) on it , as well as navigation properties and $expand will also not behave properly.
I've been banging my head against this for an embarrassing amount of time, and appreciate any help. I have what I think is a simple scenario where I'm trying to retrieve and update an entity if it exists, or create a new if it doesn't. There's a parent entity, and that part seems to work fine. I create the child key like this:
Key someKey = KeyFactory.createKey(parent.getKey(), CHILD_KIND, child.getUniqueStringValue());
According to the documents I read doing a get on this would return the entity if it existed:
Entity someChild = datastore.get(someKey);
But it doesn't. Instead I have to do a:
Query query = new Query(CHILD_KIND, someKey);
Entity someChild = datastore.prepare(query).asSingleEntity();
to find it. If I try to log the someKey.toString() value, they look the same during creation as they do during a search, but it still only finds them if I do the query instead of the get. I'm missing something stupid and obvious and searching has gotten me nowhere over the course of about a week, so I appreciate any help.
Thanks,
Mike
Edit:
To clarify how I'm creating the child entity, it's like this:
Key someKey = KeyFactory.createKey(parent.getKey(), CHILD_KIND, child.getUniqueStringValue());
Entity someChild = new Entity(CHILD_KIND, someKey);
someChild.setProperty("desc", child.getUniqueStringValue());
someChild.setProperty("createTime", child.getCreateTime());
// and then a few more values that are timestamps or null
There is a problem in the way you create a child entity. It should be:
Entity someChild = new Entity(CHILD_KIND, parent.getKey());
or
Entity someChild = new Entity(CHILD_KIND, child.getUniqueStringValue(), parent.getKey());
Also, I am not sure why you use child.getUniqueStringValue() instead of a simple Long id, which takes less space.
The problem is that you are confusing Parent_Key with Key.
This line:
Entity someChild = new Entity(CHILD_KIND, someKey);
Creates an Entity of the kind "CHILD_KIND" with parent entity of key "someKey". See this document for details [1].
When you do a simple datastore.get(key), you are using the Entity's own key, not the parent key. So what you need to do is use KeyFactory to get the Entity Key from its Parent Key, Kind, Name. The details can be found here [2] and here [3].
[1] - https://cloud.google.com/appengine/docs/java/javadoc/com/google/appengine/api/datastore/Entity
[2] - https://cloud.google.com/appengine/docs/java/datastore/entities#Java_Retrieving_an_entity
[3] - https://cloud.google.com/appengine/docs/java/javadoc/com/google/appengine/api/datastore/KeyFactory
I am trying to use the new Amazon DynamoDB JSON API to add/overwrite key-value pairs in a JSON attribute called "document". Ideally, I would like simply to structure my write calls to send the KV pairs to add to the attribute, and have Dynamo create the attribute if it does not already exist for the given primary key. However if I try this with just a straightforward UpdateItemSpec:
PrimaryKey primaryKey = new PrimaryKey("key_str", "mapKey");
ValueMap valuesMap = new ValueMap().withLong(":a", 1234L).withLong(":b", 1234L);
UpdateItemSpec updateSpec = new UpdateItemSpec().withPrimaryKey(primaryKey).withUpdateExpression("SET document.value1 = :a, document.value2 = :b");
updateSpec.withValueMap(valuesMap);
table.updateItem(updateSpec);
I get com.amazonaws.AmazonServiceException: The document path provided in the update expression is invalid for update, meaning DynamoDB could not find the given attribute named "document" to which to apply the update.
I managed to approximate this functionality with the following series of calls:
try {
// 1. Attempt UpdateItemSpec as if attribute already exists
} catch (AmazonServiceException e) {
// 2. Confirm the exception indicated the attribute was not present, otherwise rethrow it
// 3. Use a put-if-absent request to initialize an empty JSON map at the attribute "document"
// 4. Rerun the UpdateItemSpec call from the above try block
}
This works, but is less than ideal as it will require 3 calls to DynamoDB every time I add a new primary key to the table. I experimented a bit with the attribute_not_exists function that can be used in Update Expressions, but wasn't able to get it to work in the way I want.
Any Dynamo gurus out there have any ideas on how/whether this can be done?
I received an answer from Amazon Support that it is not actually possible to accomplish this with a single call. They did suggest to reduce the number of calls when adding the attribute for a new primary key from 3 to 2, by using the desired JSON map in the put-if-absent request rather than an empty map.
each user can have many questions. questions can only have one user. is the following correct
Key questionKey = KeyFactory.createKey("Questions", userId);
Entity questionEntity = new Entity("Question", questionKey);
questionEntity.setProperty("questionCategory", questionCategory);
...
The given usage is wrong. For the question, you are creating key using kind and userid . This implies the corresponding entity is of Kind="Questions" and id=userid and no parents. This is wrong and you will start getting errors once you have more than 1 question for a user as they will all have the same key.
Ideally what you need is that for a question entity, declare its kind as question and parent as the user as follows :
1, If using manually generated id or name for a question , then :
Key questionKey = KeyFactory.createKey(userkey, "Questions", questionidorname);
2, If using app engine's auto generate id, then no need create key, instead create entity as:
Entity questionEntity = new Entity("Questions",
userkey)
Here userkey is the key of a user entity
I am using Google App Engine with the Datastore interface.
Whenever I'm trying to update an entity, a whole new entity is created, this is despite the fact that I'm positive I am saving the same entity, meaning it has the same key for sure.
This is my code:
Key key=KeyFactory.createKey("user",Long.parseLong(ID));
DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
Entity entity=new Entity("user",key);
entity.setProperty // ...whatever, updating the properties
datastore.put(entity); //by putting an entity it's supposed to
// either create a new one if non exists, or update an entity if it already exists
I am sure that the key is the same during all updates as is confirmed in my admin console:
id=3001 600643316
id=3002 600643316
id=3003 600643316
a bunch of entities with the same key (600643316) is created.
The datastore only lets the app create a new entity with a String key name, not a numeric ID. Numeric IDs are system-assigned IDs. If the Key has a numeric ID but not a String key name, then the datastore will ignore it and replace it with a system-assigned numeric ID.
In your example, if ID is a string, then you can just remove the Long.parseLong() bit, or convert it back to a String. KeyFactory.createKey(String kind, String name) creates a Key with a key name.
So it seems Dan is correct and this is the correct way to do it , as explained in google's guides if you want your app to build keys from unique keys that you create you need to use strings .
"You specify whether an entity ought to use an app-assigned key name string or a system-assigned numeric ID as its identifier when you create the object. To set a key name, provide it as the second argument to the Entity constructor:
Entity employee = new Entity("Employee","asalieri");" It seems you're correct , in their example the second argument is indeed a string – user1032663