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

{  
   "_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"}
  ] 
}

我该怎么做呢?


当前回答

另一种有趣的方法是使用$编校,这是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,这可能会剥离整个文档,这是我们不想要的。

其他回答

对于MongoDB的新版本,略有不同。

对于db.collection.find,可以使用find的第二个参数,键为projection

db.collection.find({}, {projection: {name: 1, email: 0}});

你也可以使用.project()方法。 然而,它不是原生的MongoDB方法,它是大多数MongoDB驱动程序(如Mongoose, MongoDB Node.js驱动程序等)提供的方法。

db.collection.find({}).project({name: 1, email: 0});

如果你想用findOne,这和find是一样的

db.collection.findOne({}, {projection: {name: 1, email: 0}});

但是findOne没有.project()方法。

MongoDB 2.2新的$elemMatch投影操作符提供了另一种方法来修改返回的文档,使其只包含第一个匹配的形状元素:

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

返回:

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

在2.2中,还可以使用$ projection操作符,其中投影对象字段名中的$表示查询中该字段的第一个匹配数组元素的索引。下面返回与上面相同的结果:

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

更多细节请参考=

Mongo db官方参考

suppose you have document like this (you can have multiple document too) - { "_id": { "$oid": "63b5cfbfbcc3196a2a23c44b" }, "results": [ { "yearOfRelease": "2022", "imagePath": "https://upload.wikimedia.org/wikipedia/en/d/d4/The_Kashmir_Files_poster.jpg", "title": "The Kashmir Files", "overview": "Krishna endeavours to uncover the reason behind his parents' brutal killings in Kashmir. He is shocked to uncover a web of lies and conspiracies in connection with the massive genocide.", "originalLanguage": "hi", "imdbRating": "8.3", "isbookMark": null, "originCountry": "india", "productionHouse": [ "Zee Studios" ], "_id": { "$oid": "63b5cfbfbcc3196a2a23c44c" } }, { "yearOfRelease": "2022", "imagePath": "https://upload.wikimedia.org/wikipedia/en/a/a9/Black_Adam_%28film%29_poster.jpg", "title": "Black Adam", "overview": "In ancient Kahndaq, Teth Adam was bestowed the almighty powers of the gods. After using these powers for vengeance, he was imprisoned, becoming Black Adam. Nearly 5,000 years have passed, and Black Adam has gone from man to myth to legend. Now free, his unique form of justice, born out of rage, is challenged by modern-day heroes who form the Justice Society: Hawkman, Dr. Fate, Atom Smasher and Cyclone", "originalLanguage": "en", "imdbRating": "8.3", "isbookMark": null, "originCountry": "United States of America", "productionHouse": [ "DC Comics" ], "_id": { "$oid": "63b5cfbfbcc3196a2a23c44d" } }, { "yearOfRelease": "2022", "imagePath": "https://upload.wikimedia.org/wikipedia/en/0/09/The_Sea_Beast_film_poster.png", "title": "The Sea Beast", "overview": "A young girl stows away on the ship of a legendary sea monster hunter, turning his life upside down as they venture into uncharted waters.", "originalLanguage": "en", "imdbRating": "7.1", "isbookMark": null, "originCountry": "United States Canada", "productionHouse": [ "Netflix Animation" ], "_id": { "$oid": "63b5cfbfbcc3196a2a23c44e" } }, { "yearOfRelease": "2021", "imagePath": "https://upload.wikimedia.org/wikipedia/en/7/7d/Hum_Do_Hamare_Do_poster.jpg", "title": "Hum Do Hamare Do", "overview": "Dhruv, who grew up an orphan, is in love with a woman who wishes to marry someone with a family. In order to fulfil his lover's wish, he hires two older individuals to pose as his parents.", "originalLanguage": "hi", "imdbRating": "6.0", "isbookMark": null, "originCountry": "india", "productionHouse": [ "Maddock Films" ], "_id": { "$oid": "63b5cfbfbcc3196a2a23c44f" } }, { "yearOfRelease": "2021", "imagePath": "https://upload.wikimedia.org/wikipedia/en/7/74/Shang-Chi_and_the_Legend_of_the_Ten_Rings_poster.jpeg", "title": "Shang-Chi and the Legend of the Ten Rings", "overview": "Shang-Chi, a martial artist, lives a quiet life after he leaves his father and the shadowy Ten Rings organisation behind. Years later, he is forced to confront his past when the Ten Rings attack him.", "originalLanguage": "en", "imdbRating": "7.4", "isbookMark": null, "originCountry": "United States of America", "productionHouse": [ "Marvel Entertainment" ], "_id": { "$oid": "63b5cfbfbcc3196a2a23c450" } } ], "__v": 0 } ======= mongo db query by aggregate command - mongomodels.movieMainPageSchema.aggregate( [ { $project: { _id:0, // to supress id results: { $filter: { input: "$results", as: "result", cond: { $eq: [ "$$result.yearOfRelease", "2022" ] } } } } } ] )

更好的是,您可以使用$slice在匹配的数组元素中查询,这有助于返回数组中的重要对象。

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

当您知道元素的索引时,$slice是有用的,但有时您需要 匹配条件的数组元素。您可以返回匹配的元素 使用$操作符。

MongoDB 2.2+中的新的聚合框架为Map/Reduce提供了一种替代方案。$unwind操作符可以用来将你的形状数组分离成一个可以匹配的文档流:

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"
  }}
)

结果:

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