0

I am having a MongoDB document like this

{
    "_id" : "toy_in_en_L02B",
    "modelCode" : "L02B",
    "path" : "/toy/in/en",
    "dataPath" : "/toy/in/en/L02B",
    "basicModelInformation" : {
        "name" : "News",
        "startingPrice" : "1234.0"
    },
    "grades" : {
        "grades" : [ 
            {
                "key" : "LVL001",
                "dataPath" : "/toy/in/en/L02B",
                "name" : "XE P",
                "price" : "1234.0"
            }, 
            {
                "key" : "LVL002",
                "dataPath" : "/toy/in/en/L02B",
                "name" : "XE P",
                "price" : "1234.0"
            },
            {
                "key" : "LVL003",
                "dataPath" : "/toy/in/en/L02B",
                "name" : "XE P",
                "price" : "1234.0"
            },
            {
                "key" : "LVL004",
                "dataPath" : "/toy/in/en/L02B",
                "name" : "XE P",
                "price" : "1234.0"
            }

        ]
    }
}

Now I want to retrieve a complete Document with having only one grade as LVL001. But when I am querying this like

db.getCollection('models').find({$and: [{"dataPath" : "/nissan/in/en/L02B" }, {"grades.grades" : {$elemMatch: {"key":"LVL002"}}}]})

I am getting all the grades.

I already checked the thread Retrieve Queried Element but not getting it.

My code is using the Spring @Query. Any json query parameter for this will also be useful.

Ashish
  • 341
  • 2
  • 7
  • 17
  • refer https://stackoverflow.com/questions/3985214/retrieve-only-the-queried-element-in-an-object-array-in-mongodb-collection – Vinod Jun 20 '17 at 15:33
  • This is the first thread which I checked. This is already mentioned in my question. But I am not getting the desired result. I want to have only one element grade (which is requested) in my query result. – Ashish Jun 20 '17 at 18:34
  • What is your mongo server version ? – s7vr Jun 21 '17 at 11:37

1 Answers1

1

With Mongo 2.2+ you can use the new Aggregation Framework.

db.getCollection('models').aggregate([
    { $unwind : "$grades.grades" },
    { $match : {"dataPath": "/nissan/in/en/L02B", 
                "grades.grades.key": "LVL002"}}
])

Unwind deconstructs an array field from the input to output a document for each element. Using the document you posted as an example, with unwind you will have 4 documents. Then with match you just filter the documents you want.

Rodrigo Villalba Zayas
  • 5,326
  • 2
  • 23
  • 36
  • Thanks Rodrigo. It works fine when we have to run a query against for one grade. But when I try to run it for multiple grades like db.getCollection('models').aggregate([ { $unwind : "$grades.grades" }, { $match : {"dataPath": "/nissan/in/en/L02B", "grades.grades.key": {$in: [ "LVL002", "LVL003"]}}} ]) It comes up with 2 documents. Each document contains one grade. I want to have a model which can contain all the grades under one document. – Ashish Jun 21 '17 at 09:18
  • That's another question my friend! unwind won't be useful for that scenario. – Rodrigo Villalba Zayas Jun 21 '17 at 14:53
  • Any help on that would be useful :) ! – Ashish Jun 22 '17 at 14:19