Migrating from createQuery() to find() doesn't work as expected
See original GitHub issuePlease ask your question and provide whatever background or supporting information you think might be relevant:
Hi @evanchooly, I’m in the process of migrating from v1.6 to v2.0 and I’m having some trouble re-writing queries from createQuery()
to find()
because of some counter-intuitive behaviour
Code snippets
When using 1.6 the following simple mongo query would work:
PricingVersion potential = datastore.createQuery(PricingVersion.class).order("-createdAt").get();
// null check and logging
return potential;
In 2.0 this becomes:
return datastore.find(PricingVersion.class)
.iterator(new FindOptions()
.sort(descending("createdAt")))
.next();
However the MongoCursor throws a NoSuchElementException.
Logs
After some digging in the logs I found that the mongo command has changed from (v1.6):
{"find": "PricingVersion", "sort": {"createdAt": -1}, "limit": 1, "$db": "datahub_v", ... }
to (v2.0):
{"find": "pricingVersion", "filter": {"_t": {"$in": ["PricingVersion"]}}, "sort": {"createdAt": -1}, "$db": "datahub_v", ...}
I would expect {"find": "PricingVersion"}
After reading through the source code I found I could workaround this issue by using find(final String collection, final Class<T> type)
from here. My code became
return datastore.find("PricingVersion", PricingVersion.class)
.iterator(new FindOptions()
.sort(descending("createdAt")))
.next();
But this still throws a NoSuchElementException…
Here is the mongo request log:
{"find": "PricingVersion", "filter": {"_t": {"$in": ["PricingVersion"]}}, "sort": {"createdAt": -1}, "$db": "datahub_v", ...}
How can I properly retrieve the list of PricingVersions from mongo in morphia v2.0?
Additional info
In the migration to morphia v2.0, a field was removed in the PricingVersion class:
# deprecated price curve
@Reference
@JsonAlias("curves")
private Map<String, Curve> oldcurves = new HashMap<>();
On top of being deprecated, this field also caused problem in morphia 2.0 because the @ Reference
annotation requires Map to have an id.
Is this related to the fact the query above is returning a NoSuchElementExceptionand not the list of pricing versions as expected?
Aside - refactoring
In https://github.com/MorphiaOrg/morphia/blob/master/morphia/src/main/java/dev/morphia/query/MorphiaQuery.java#L62 you might want to change the order of the parameters from
MorphiaQuery(final Datastore datastore, final String collectionName, final Class<T> clazz)
to
MorphiaQuery(final Datastore datastore, final Class<T> clazz, final String collectionName)
to match the overloaded constructor just below which looks like
MorphiaQuery(final Datastore datastore, final Class<T> clazz, final Document query)
It makes it slightly more readable and less confusing when reading this if statement
Thanks for reading this far! 😄
Issue Analytics
- State:
- Created 3 years ago
- Comments:6 (3 by maintainers)
I’ll stick to
MapperOptions#legacy()
for now then. I’ll keep an eye out on the docs and start planning the migration. Thanks for your help! 👍What you’re running in to is, well, two things: a change in the default behavior and lack of sufficient documentation. How are you building your
MapperOptions
? Are you explicitly building aMapperOptions
? In 1.6dev.morphia.mapping.MapperOptions#builder()
was deprecated in favor ofdev.morphia.mapping.MapperOptions#legacy()
because some defaults were going to change. If you don’t useMapperOptions
directly, you’re getting the new defaults automatically.One of those changes is the ability to set collection/field naming strategies. In the case of collections that is now
camelCase
which is what you’re seeing. If update your code to usedev.morphia.mapping.MapperOptions#legacy()
when creating yourMapper
, you’ll get the “correct” class name. You can also usedev.morphia.mapping.MapperOptions#builder()
directly and just update the naming strategy to your personal preference.This is a gap in the migration docs which I’ll update shortly to correct.
And yes, that constructor order is annoyingly inconsistent. 😃