I'm using Objectify v5.1.5 and am attempting to run a query that uses an "in"
query along with an orderBy clause.
SELECT * FROM MyEntity WHERE someProperty IN ( 'value1', 'value2') ORDER BY
some.other.property DESC
This produces the following error on my system:
"The provided keys-only multi-query needs to perform some sorting in memory.
As a result, this query can only be sorted by the key property as this is the
only property that is available in memory."
Which would make since if I was using a keys only query. However I am not
attempting to use a keys only query. After some digging around and enabling the
"FINEST" logging, I found the following:
FINEST com.googlecode.objectify.impl.QueryEngine queryHybrid: Starting hybrid
query
Objectify is enabling a hybrid query which automatically converts the query to
a keys only query, thus the error.
We just recently converted from objectify 4 to 5 and that conversion is what
caused this error. I noticed that Objectify 4 and 5 handles the logic to use a
hybrid query differently.
The following is how objectify 4 decides this should be a hybrid query. Notice
the "hasMulti && hasNonKeyOrder" makes the query non-hybrid.
https://code.google.com/p/objectify-appengine/source/browse/src/main/java/com/go
oglecode/objectify/impl/QueryImpl.java?name=v4
/** Produces the basic iterable on results based on the current query. Used to
generate other iterables via transformation. */
private QueryResultIterable<T> resultIterable() {
boolean hybridize = hybrid;
if (!hasExplicitHybrid) {
// These are the special conditions we know about. It may expand.
if (hasMulti && hasNonKeyOrder)
hybridize = false;
}
if (hybridize)
return loader.createQueryEngine().queryHybrid(this.getActualQuery(), this.fetchOptions());
else
return loader.createQueryEngine().queryNormal(this.getActualQuery(), this.fetchOptions());
}
The following is how objectify 5 decides if the query should be a hybrid query.
This is basically saying that if caching is enabled, do a hybrid query. No
check for multi queries with sort orders by a property.
https://code.google.com/p/objectify-appengine/source/browse/src/main/java/com/go
oglecode/objectify/impl/QueryImpl.java?name=master
/** Produces the basic iterable on results based on the current query. Used to
generate other iterables via transformation. */
private QueryResultIterable<T> resultIterable() {
if (!actual.getProjections().isEmpty())
return loader.createQueryEngine().queryProjection(this.getActualQuery(), this.fetchOptions());
else if (shouldHybridize())
return loader.createQueryEngine().queryHybrid(this.getActualQuery(), this.fetchOptions());
else
return loader.createQueryEngine().queryNormal(this.getActualQuery(), this.fetchOptions());
}
/**
* @return true if we should hybridize this query
*/
private boolean shouldHybridize() {
if (hybrid != null)
return hybrid;
// If the class is cacheable
if (classRestriction != null && loader.getObjectifyImpl().getCache() && fact().getMetadata(classRestriction).getCacheExpirySeconds() != null)
return true;
return false;
}
Objectify should recognize when a hybrid query is not appropriate and use a
normal query instead.
Original issue reported on code.google.com by brian.ch...@aawhere.com on 3 Apr 2015 at 4:56
Original issue reported on code.google.com by
brian.ch...@aawhere.com
on 3 Apr 2015 at 4:56