Querying Subdocument and Returning Matching Subdoc

2019-08-26 01:58发布

cExample Mongo Document

{
  "_id": ObjectId("5652e77f21b0f1f2692558a1"),
  "category": "clothing",
  "Brand": [
    {
      "name": "Adidas",
      "key": "Adidas"
    },
    {
      "name": "Reebok",
      "key": "Reebok"
    },
    {
      "name": "Puma",
      "key": "Puma"
    }
  ],
  "Color": [
    {
      "name": "Red",
      "key": "Red"
    },
    {
      "name": "Green",
      "key": "Green"
    },
    {
      "name": "Blue",
      "key": "Blue"
    }
  ]
}

Now I want to search for Brands where name is either Adidas or Puma. Other requerement is to return sub document only so I tried query given below

find( { "Brand.name" : { $in : ["Reebok", "Adidas"]}},{"Brand" : 1, "_id" : 0})

But its returning me all three objects of Brand array

{
    "Brand" : [ 
        {
            "name" : "Adidas",
            "key" : "Adidas"
        }, 
        {
            "name" : "Reebok",
            "key" : "Reebok"
        }, 
        {
            "name" : "Puma",
            "key" : "Puma"
        }
    ]
}

I can sertainly do it through Javascript as well (Iterating through retuned array and metching values) but Is there any way to get my purpose solved with Mongo Query only.

Note : In NoSql Systems, where JSON documents are supported, biggest difference is these systems doesn't support relationships but you can always maintain relations by subdocuments. If such queries (mentioned above) are not possible then I think holding data in subdocument form is not good practise as you can not query it as you want. Expert Thoughts on this????

标签: mongodb nosql
2条回答
虎瘦雄心在
2楼-- · 2019-08-26 02:18

$in in find query is designed to return documents rather than sub documents. In your case mongoDB has provided the aggregation framework. This will help you filter sub documents.

For mongoDB <= 3.0.x

db.collection.aggregate(
  { $project: { Brand: 1}},
  { $unwind: '$Brand'},
  { $match: { "Brand.name" : { $in : ["Reebok", "Adidas"]}}},
  { $group: { _id: '$_id', Brand: {$push : '$Brand' }}}
)

MongoDB 3.2 way

db.collection.aggregate([
   {
      $project: {
         Brand: {
            $filter: {
               input: "$Brand",
               as: "Brand",
               cond: { "$$Brand.name": { $in : ["Reebok", "Adidas"]}}
            }
         }
      }
   }
])
查看更多
爱情/是我丢掉的垃圾
3楼-- · 2019-08-26 02:23

It work correct. In the mongo documentation is written as follows:

The $in operator selects the documents where the value of a field equals any value in the specified array.

It returned you the document, that contain "Reebok" or "Adidas".

查看更多
登录 后发表回答