Reputation: 35276
This query works, the fullPath
field is a List<String>
:
KeyLookup lookup
= ofy().load().type(KeyLookup.class).filter("fullPath IN", key.getFullPath()).first().get();
The query above also fetch the entities having the same String
elements in the List<String>
as with key.getFullPath()
, however it also fetches those entities having the same String in the list with additional more String in the list.
How can I filter only those Entity having the exact same elements in the list, like "no more, no less"
Update:
For example
One entity (say Object1) field fullPath contains:
Another entity (say Object2) field fullPath contains:
And key.getFullPath contains:
Then the query above will return Object1
and Object2
, however what I need is that it only returns Object2
Upvotes: 0
Views: 1740
Reputation: 13556
Assuming you want an exact match (no more values, no fewer values), there is no "native datastore" way to implement this. IN gets you an or operation, multiple calls to filter() gives you an and operation - neither of which are exact matches. However, there are ways.
Option 1: Join the list into a single indexed property
Concatenate all the items in the list into a single value and store that as a synthetic indexed property. Maybe you need to normalize it depending on the significance of order or case. Query on that property, not the list property.
This will only work if the concatenated value is guaranteed to fit under 500 chars. Seems unlikely. Instead you probably want...
Option 2: Index and query on a hash of the list
fullPathHash
. It doesn't need to be cryptographically secure; MD5 is fine.fullPathHash
; you don't need to index the list property.Upvotes: 3
Reputation: 3115
This is expected since when comparing two lists in a query, what actually happens under the hood is that the datastore fires multiple queries for each of the values in the filter list. Thus, when you query for Object2
, four queries are executed for each of the values in Object2
. Since, Object1
is a "subset" of Object2
, it also matches the queries. This is the reason you get both Object1
and Object2
.
You can modify your queries to use the AND
operator in order to force exact matching. So, you can have the following:
Query<KeyLookup> q = ofy().load().type(KeyLookup.class);
for (String f : key.getFullPath()) {
q = q.filter("fullPath", f);
}
KeyLookup lookup = q.first().get();
Hope this helps.
Upvotes: 1