Mapping to MongoDB
This page aims at collecting thoughs on how to map to MongoDB. While it essentially focus on queries, we can imagine sections pertaining to
data mapping or option mapping etc. It also should list the set of use cases that MongoDB covers well but where Hibernate OGM is not good at.
Mapping JP-QL queries
Here are a list of queries, how can these be mapped in MongoDB query language? Note that this list excludes cross document joins - at least initially.
Cat is an entity
Owner is an embedded object
Address is an embedded object
jpql: select o from java.lang.Object o //return all mapped objects from the database
mongodb: not possible to do a single query across collections. discuss further regarding use of polymorphic collections
jpql: select c from Cat c //return all Cats
mongodb: db.cats.find()
jpql: select c.name from Cat c //return all Cat names
mongodb: db.cats.find({}, {'name' : 1)})
jpql: select c from Cat c where c.name = :name //return cats of a given name
mongodb: db.cats.find({'name' : name})
jpql: select c from Cat c where c.owner.address.city = :city //return all cats whose owner lives in a given city
mongodb: db.cats.find({'owner.address.city' : city})
jpql: select count(c) from Cat c where c.weight > :weight // return the number of cats whose weight is greater than weight
mongodb: db.cats.find({'weight' : {$gt : weight}}).count()
jpql: select cat, count( elements(cat.kittens) ) from eg.Cat cat group by cat // return each cat and for each cat the number of kittens
mongodb: db.cats.find(...)
jpql: select distinct cat.name from Cat cat // return the list of distinct cat names
mongodb: db.cats.distinct('name')
jpql: select distinct cat.name from Cat cat // return the list of distinct cat names where weight is greater than weight
mongodb: db.cats.distinct('name', {'weight' : {$gt : weight})
jpql: select cat from eg.Cat cat where cat.mate.name is not null // find all cats available for shagging
mongodb: db.cats.find({'mate.name' : {$exists : true}})
jpql: select cat from eg.Cat cat where cat.name between 'Alfonse' and 'Gertrude' // get all cats whose name is alphabetically between Alfonse and Gertrude
mongodb: db.cats.find({'name' : {$lte : 'Alfonse', $gte : 'Gertrude'}})
jpql: from eg.DomesticCat cat where cat.name not in ( 'foo', 'bar', 'baz' ) //get all cats not named after computer jokes
mongodb: db.cats.find({'name' : {$nin : ['foo', 'bar', 'baz']}}) // question: do Cat queries find DomesticCat as well? We need to talk about how we might handle polymorphic collections
jpql: from eg.DomesticCat cat where cat.name in ( 'foo', 'bar', 'baz' ) //get all cats named after a computer joke
mongodb: db.cats.find({'name' : {$in : ['foo', 'bar', 'baz']}})
jpql: from Order o where minelement(order.items) > 100 //get all orders containing more than 100 items
mongodb: db.cats.find(...)
jpql: from eg.DomesticCat cat order by cat.name asc, cat.weight desc, cat.birthdate // get cats ordered by name and decreasing weight and birthdate
mongodb: db.cats.find().sort({'name' : 1, 'weight' : -1, birthdate : -1}) // should there be a 'desc' after cat.birthdate, based on the comment?
jpql: select cat.color, sum(cat.weight), count(cat) from eg.Cat cat group by cat.color // get the total weight and number of cats per color
mongodb: db.cats.aggregate( { $group: { _id: { color: 1 }, weight: { $sum: $weight }, count: { $sum: 1} } ) // note that the aggegate command requires MongoDB version >= 2.2
Use cases not well covered by Hibernate OGM
The ability to update data without having to read it is used in MongoDB to cover use cases that might not work properly in JPA.
One use case is counter increments for monitoring. The counter is +1'd by several servers and MongoDB minimizes contention by
processing these push only operations
Another use case described by Jeff is the ability to add elements to a collection (with set or bag semantic, any other like map or list?) without
having to read the whole collection. Hibernate sort of has such capability with what is called extra-lazy collections. We need to investigate if
Emmanuel's intuition is good and that this can effectively be mapped. See http://www.mongodb.org/display/DOCS/Updating/#Updating-ModifierOperations
for a full list of Mongodb update operations.
Comments