Spring-Data mongodb querying multiple classes stored in the same collection


With Spring-Data, you can use the @Document annotation to specify which collection to save the object to. Say I have two classes, Student and Teacher, both persisted into the people collection. When I execute the following code:

mongo.find(new Query(), Teacher.class);

the result contains both Student and Teacher. Looking in the data created by Spring-Data, each document contains a "_class" field which indicate which class it is persisted from.

This is field not used in find as an filter to return only Teacher? How do I query for only Teacher other than doing this:

mongo.find(new Query().addCriteria(where("_class").is(Teacher.class.getCanonicalName()), Teacher.class);
By : ltfishie


This is more or less a question of how to design your collections. As Mongo does not know anything about types we have to add the additional metadata to be able to distinguish documents from each other. Thus when querying you'll need to add these constraints to the query as well. Note that you can refer to the _class key through DefaultMongoTypeMapper.DEFAULT_TYPE_KEY.

We thought about adding some API to the query to express one only wants to get documents of a given type like this:

mongo.find(new Query(Teacher.class), Teacher.class);

It still feels a bit weird that you have to state domain class twice (which makes sense if you want to restrict the results to documents of a given type but map them onto an different class). Beyond that we could only restrict the results to documents that carry exactly that type as the types are stored as Strings and inheritance can only be applied if the class has already been loaded. So when querying for documents with type Person we'd have to load all documents first, try to lookup the type, do the type check and potentially throw away the result which is sub-optimal for performance reasons.

Another option would be to store all types a class is assignable to (pretty much all interfaces and superclasses except Object maybe) but that would cause quite an amount of data being stored. This could be in turn approached by adding a flag to the @Document annotation.

Bottom line: currently, there's no other way but feel free to raise JIRA tickets if you have suggestions how this can be improved.

This video can help you solving your question :)
By: admin