假设我的收藏中有以下文件:

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

做查询:

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

Or

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

返回匹配的文档(文档1),但总是使用形状中的ALL数组项:

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

但是,我想只获得包含color=red的数组的文档(文档1):

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

我该怎么做呢?


当前回答

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

其他回答

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

另一种有趣的方法是使用$编校,这是MongoDB 2.6的新聚合特性之一。如果您使用的是2.6,则不需要$unwind,如果您使用的是大型数组,$unwind可能会导致性能问题。

db.test.aggregate([
    { $match: { 
         shapes: { $elemMatch: {color: "red"} } 
    }},
    { $redact : {
         $cond: {
             if: { $or : [{ $eq: ["$color","red"] }, { $not : "$color" }]},
             then: "$$DESCEND",
             else: "$$PRUNE"
         }
    }}]);

$redact“根据存储在文档本身中的信息限制文档的内容”。所以它只会在文档内部运行。它基本上扫描你的文档从上到下,并检查它是否与你的if条件在$cond中匹配,如果有匹配,它将保留内容($$ descent)或删除($$PRUNE)。

在上面的例子中,第一个$match返回整个形状数组,$编校将其分解为预期的结果。

注意{$not:"$color"}是必要的,因为它也会扫描顶部的文档,如果$ react没有在顶部找到一个颜色字段,这将返回false,这可能会剥离整个文档,这是我们不想要的。

感谢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"
    }
]}

你只需要运行query

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

此查询的输出为

{
    "_id" : ObjectId("562e7c594c12942f08fe4192"),
    "shapes" : [ 
        {"shape" : "circle", "color" : "red"}
    ]
}

正如你所期望的那样,它会从数组中给出匹配颜色的精确字段:'red'。

使用聚合函数和$project获取文档中的特定对象字段

db.getCollection('geolocations').aggregate([ { $project : { geolocation : 1} } ])

结果:

{
    "_id" : ObjectId("5e3ee15968879c0d5942464b"),
    "geolocation" : [ 
        {
            "_id" : ObjectId("5e3ee3ee68879c0d5942465e"),
            "latitude" : 12.9718313,
            "longitude" : 77.593551,
            "country" : "India",
            "city" : "Chennai",
            "zipcode" : "560001",
            "streetName" : "Sidney Road",
            "countryCode" : "in",
            "ip" : "116.75.115.248",
            "date" : ISODate("2020-02-08T16:38:06.584Z")
        }
    ]
}