1

I have document with nested document reviews:

{
        "_id" : ObjectId("53a5753937c2f0ef6dcd9006"),
        "product" : "Super Duper-o-phonic",
        "price" : 11000000000,
        "reviews" : [
                {
                        "user" : "fred",
                        "comment" : "Great!",
                        "rating" : 5
                },
                {
                        "user" : "Tom",
                        "comment" : "Great again!",
                        "rating" : 5
                },
                {
                        "user" : "Tom",
                        "comment" : "I agree with fred somewhat",
                        "rating" : 4
                }
        ]
}

I want to find only those reviews whose rating is 5.

Final query should select product price and two documents from reviews whose rating is 5.

The last query I tried is :

db.testData.find({'reviews':{$elemMatch:{'rating':{$gte:5}}}}).pretty()

It's strange but it doesn't work.

How to do this in mongodb?

Volodymyr Levytskyi
  • 3,364
  • 9
  • 46
  • 83

2 Answers2

4

If you only want a single sub-doc from reviews whose rating is 5, you can use the $ positional projection operator to include the first element of reviews that matches your query:

db.test.find({'reviews.rating': 5}, {product: 1, price: 1, 'reviews.$': 1})

If you want all reviews elements with a rating of 5 (instead of just the first) you can use aggregate instead of find:

db.test.aggregate([
    // Only include docs with at least one 5 rating review
    {$match: {'reviews.rating': 5}}, 
    // Duplicate the docs, one per reviews element
    {$unwind: '$reviews'}, 
    // Only include the ones where rating = 5
    {$match: {'reviews.rating': 5}}, 
    // Only include the following fields in the output
    {$project: {product: 1, price: 1, reviews: 1}}])
JohnnyHK
  • 305,182
  • 66
  • 621
  • 471
  • I just tried this and it doesn't work if I select two documents from `reviews` with rating 5. because `reviews.$` ensures that only the first matching document is included in result. – Volodymyr Levytskyi Jun 21 '14 at 14:42
  • @VolodymyrLevytskyi Use the `aggregate` approach if you want to include all rating 5 reviews instead of just the first one. – JohnnyHK Jun 21 '14 at 15:03
0

Take a look up here: MongoDB - how to query for a nested item inside a collection?

Just in case you thought about this: If you try to accomplish this with $elemMatchit will jsut return the first matching review. http://docs.mongodb.org/manual/reference/operator/projection/elemMatch/

Community
  • 1
  • 1
Zarathustra
  • 2,853
  • 4
  • 33
  • 62