僅檢索MongoDB集合中對象數組中的查詢元素

假設您的收藏夾中包含如下文檔: javascript

{  
   "_id":ObjectId("562e7c594c12942f08fe4192"),
   "shapes":[  
      {  
         "shape":"square",
         "color":"blue"
      },
      {  
         "shape":"circle",
         "color":"red"
      }
   ]
},
{  
   "_id":ObjectId("562e7c594c12942f08fe4193"),
   "shapes":[  
      {  
         "shape":"square",
         "color":"black"
      },
      {  
         "shape":"circle",
         "color":"green"
      }
   ]
}

進行查詢: java

db.test.find({"shapes.color": "red"}, {"shapes.color": 1})

要麼 mongodb

db.test.find({shapes: {"$elemMatch": {color: "red"}}}, {"shapes.color": 1})

返回匹配的文檔(文檔1) ,但始終具備shapes全部數組項: 數組

{ "shapes": 
  [
    {"shape": "square", "color": "blue"},
    {"shape": "circle", "color": "red"}
  ] 
}

可是,我只想使用包含color=red的數組來獲取文檔(文檔1)框架

{ "shapes": 
  [
    {"shape": "circle", "color": "red"}
  ] 
}

我怎樣才能作到這一點? ide


#1樓

MongoDB 2.2+中的新聚合框架提供了Map / Reduce的替代方案。 $unwind運算符可用於將您的shapes數組分紅可匹配的文檔流: spa

db.test.aggregate(
  // Start with a $match pipeline which can take advantage of an index and limit documents processed
  { $match : {
     "shapes.color": "red"
  }},
  { $unwind : "$shapes" },
  { $match : {
     "shapes.color": "red"
  }}
)

結果是: code

{
    "result" : [
        {
            "_id" : ObjectId("504425059b7c9fa7ec92beec"),
            "shapes" : {
                "shape" : "circle",
                "color" : "red"
            }
        }
    ],
    "ok" : 1
}

#2樓

MongoDB 2.2的新的$elemMatch投影運算符提供了另外一種方法來更改返回的文檔以僅包含第一個匹配的shapes元素: 對象

db.test.find(
    {"shapes.color": "red"}, 
    {_id: 0, shapes: {$elemMatch: {color: "red"}}});

返回值: 索引

{"shapes" : [{"shape": "circle", "color": "red"}]}

在2.2中,您也能夠使用$ projection operator執行此$ projection operator ,其中投影對象字段名稱中的$表示查詢中該字段的第一個匹配數組元素的索引。 如下返回與上面相同的結果:

db.test.find({"shapes.color": "red"}, {_id: 0, 'shapes.$': 1});

MongoDB 3.2更新

從3.2發行版開始,您能夠使用新的$filter聚合運算符在投影期間過濾數組,這樣作的好處是包括全部匹配項,而不單單是第一個匹配項。

db.test.aggregate([
    // Get just the docs that contain a shapes element where color is 'red'
    {$match: {'shapes.color': 'red'}},
    {$project: {
        shapes: {$filter: {
            input: '$shapes',
            as: 'shape',
            cond: {$eq: ['$$shape.color', 'red']}
        }},
        _id: 0
    }}
])

結果:

[ 
    {
        "shapes" : [ 
            {
                "shape" : "circle",
                "color" : "red"
            }
        ]
    }
]

#3樓

與$ project一塊兒使用,更明智的作法是將其餘明智的匹配元素與文檔中的其餘元素合併在一塊兒。

db.test.aggregate(
  { "$unwind" : "$shapes" },
  { "$match" : {
     "shapes.color": "red"
  }},
{"$project":{
"_id":1,
"item":1
}}
)

#4樓

在mongodb中查找的語法是

db.<collection name>.find(query, projection);

和您編寫的第二個查詢,即

db.test.find(
    {shapes: {"$elemMatch": {color: "red"}}}, 
    {"shapes.color":1})

在這種狀況下,您在查詢部分中使用了$elemMatch運算符,而若是在投影部分中使用了此運算符,則將得到所需的結果。 您能夠將查詢記爲

db.users.find(
     {"shapes.color":"red"},
     {_id:0, shapes: {$elemMatch : {color: "red"}}})

這將爲您提供所需的結果。


#5樓

感謝JohnnyHK

在這裏,我只想添加一些更復雜的用法。

// Document 
{ 
"_id" : 1
"shapes" : [
  {"shape" : "square",  "color" : "red"},
  {"shape" : "circle",  "color" : "green"}
  ] 
} 

{ 
"_id" : 2
"shapes" : [
  {"shape" : "square",  "color" : "red"},
  {"shape" : "circle",  "color" : "green"}
  ] 
} 


// The Query   
db.contents.find({
    "_id" : ObjectId(1),
    "shapes.color":"red"
},{
    "_id": 0,
    "shapes" :{
       "$elemMatch":{
           "color" : "red"
       } 
    }
}) 


//And the Result

{"shapes":[
    {
       "shape" : "square",
       "color" : "red"
    }
]}
相關文章
相關標籤/搜索