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

{  
   "_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.getCollection('localData').aggregate([
    // Get just the docs that contain a shapes element where color is 'red'
  {$match: {'shapes.color': {$in : ['red','yellow'] } }},
  {$project: {
     shapes: {$filter: {
        input: '$shapes',
        as: 'shape',
        cond: {$in: ['$$shape.color', ['red', 'yellow']]}
     }}
  }}
])

其他回答

与$project一起,其他明智的匹配元素将与文档中的其他元素组合在一起。

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

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

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

注意:这个答案提供的解决方案在当时是相关的,在MongoDB 2.2及更高版本的新特性引入之前。如果您使用的是最新版本的MongoDB,请参阅其他答案。

字段选择器参数仅限于完整的属性。它不能用于选择数组的一部分,只能用于选择整个数组。我尝试使用$ positional操作符,但这不起作用。

最简单的方法是在客户端中过滤形状。

如果你真的需要直接从MongoDB得到正确的输出,你可以使用map-reduce来过滤形状。

function map() {
  filteredShapes = [];

  this.shapes.forEach(function (s) {
    if (s.color === "red") {
      filteredShapes.push(s);
    }
  });

  emit(this._id, { shapes: filteredShapes });
}

function reduce(key, values) {
  return values[0];
}

res = db.test.mapReduce(map, reduce, { query: { "shapes.color": "red" } })

db[res.result].find()

更多细节请参考=

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