Question

I notice strange behavior when querying the GAE datastore. Under certain circumstances Filter does not work for integer fields. The following java code reproduces the problem:

log.info("start experiment");

DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();

int val = 777;

// create and store the first entity.
Entity testEntity1 = new Entity(KeyFactory.createKey("Test", "entity1"));
Object value = new Integer(val);
testEntity1.setProperty("field", value);
datastore.put(testEntity1);

// create the second entity by using BeanUtils.
Test test2 = new Test(); // just a regular bean with an int field
test2.setField(val);

Entity testEntity2 = new Entity(KeyFactory.createKey("Test", "entity2"));

Map<String, Object> description = BeanUtilsBean.getInstance().describe(test2);
for(Entry<String,Object> entry:description.entrySet()){
    testEntity2.setProperty(entry.getKey(), entry.getValue());
}

datastore.put(testEntity2);


// now try to retrieve the entities from the database...

Filter equalFilter = new FilterPredicate("field", FilterOperator.EQUAL, val);

Query q = new Query("Test").setFilter(equalFilter);

Iterator<Entity> iter = datastore.prepare(q).asIterator();

while (iter.hasNext()) {
    log.info("found entity: " + iter.next().getKey());
}

log.info("experiment finished");

the log looks like this:

INFO: start experiment
INFO: found entity: Test("entity1")
INFO: experiment finished

For some reason it only finds the first entity even though both entities are actually stored in the datastore and both 'field' values are 777 (I see it in the Datastore Viewer)! Why does it matter how the entity is created? I would like to use BeanUtils, because it is convenient.

The same problem occurs on the local devserver and when deployed to GAE.

Was it helpful?

Solution

Ok I found out what is going on. The "problem" is that for some reason BeanUtils transforms integers into strings. A string looks exactly the same in the datastore viewer but it is of course not the same. This pretty much fooled me. I should have studied the apache BeanUtils manual or something.

OTHER TIPS

Have you given the datastore 1 second after writing before you query the data? Sometimes you don't have to (ancestor queries, perhaps) but other times you do. The GAE/J documentation will give full details.

The fact that the entities are created with BeanUtils is completely irrelevant. If the entities are in the datastore (you can see them in the viewer) and the field value is indexed (it does not show "unindexed" next to value in datastore viewer) then you can query for them using a filter. This works... its is the basic functionality of the datastore.

Given the entities are created and indexed, I suggest that Ian Marshalls suggestion is probably correct. To test this, go to the preferences for App Engine and un-tick "Enable local HRD support". This will ensure that when you write an Entity you can query for it immediately.

It is not important if you store an Integer or int or any other numeric value - they are all stored as a long value internally and when you read your value back you will get a Long (despite storing an Integer)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top