这是单个文档:

{
   _id: "...",
   firstName: "john",
   lastName:"Doe",
   cars: [
       {
           "_id": "...",
           "carName": "BMW",
           "carModel": "330",
           "carColor": "silver"
       },
       {
           "_id": "...",
           "carName": "Lexus",
           "carModel": "IS300",
           "carColor": "white"
       },
       {
           "_id": "...",
           "carName": "LADA",
           "carModel": "2106",
           "carColor": "blue"
       }
   ]
}

我只想选约翰的宝马的“汽车颜色”。
像这样的:
db.persons.findOne(
        { "firstName": "John", "cars.carName": "BMW" },
        { "_id": 0, "cars.$.carColor": 1 }
      );

但此查询返回完整对象,如下所示:
{
    cars: [
      {
         "_id": "...",
         "carName": "BMW",
         "carModel": "330",
         "carColor": "silver"
      }
}

我已经尝试了不同的查询没有。$。符号:
db.persons.findOne(
            { "firstName": "John", "cars.carName": "BMW" },
            { "_id": 0, "cars.carColor": 1 }
          );

此版本只返回“carcolor”属性,但不过滤“carname”。
这样地:
{
   cars: [
       {
          "carColor": "silver"
       },
       {
          "carColor": "white"
       },
       {
          "carColor": "blue"
       }
   ]
}

有什么想法吗?

最佳答案

为什么不起作用?
{“firstname”:“john”,“cars.carname”:“bmw”}
意思是“在哪里名字是约翰,在哪里至少有一个条目在汽车数组中,卡纳姆是“宝马”。但它返回完整的文档,而不过滤数组。
{“{id”:0,“cars.carcolor”:1}
不投射id,而是投射car数组中所有条目的carcolor。
解决方案
事实上,使用find和projection方法并不能完全达到您想要的效果。最好是这样添加$ projection operator

db.collection.find({
  firstName: "john",
  "cars.carName": "BMW"
},
{
  _id: 0,
      "cars.$": 1
    })

**RESULT**

[
  {
    "cars": [
      {
        "_id": "...",
        "carColor": "silver",
        "carModel": "330",
        "carName": "BMW"
      }
    ]
  }
]

但这种方法有缺点:
你得到了整个数组条目,而不仅仅是你想要/需要的颜色
它只返回第一个匹配的条目:如果john有两辆bmw,则只返回一辆。
更好的解决方案
幸运的是,mongodb提供了另一种方法来实现这一点,它使用聚合框架和$filter操作符:
db.collection.aggregate([
  {
    $match: {
      firstName: "john"
    }
  },
  {
    $project: {
      cars: {
        $filter: {
          input: "$cars",
          as: "cars",
          cond: {
            $eq: [
              "$$cars.carName",
              "BMW"
            ]
          }
        }
      }
    }
  },
  {
    $project: {
      _id: 0,
      "colors": "$cars.carColor"
    }
  }
])

You can try it here.
编辑:其他解决方案
您也可以尝试使用“展开/分组”阶段:
db.collection.aggregate([
  {
    $match: {
      firstName: "john"
    }
  },
  {
    $unwind: "$cars"
  },
  {
    $match: {
      "cars.carName": "BMW"
    }
  },
  {
    $group: {
      "_id": null,
      colors: {
        $push: "$cars.carColor"
      }
    }
  }
])

07-28 09:00