如何使用多个条件查找查询在 MongoDB 中指定字段?

Posted

技术标签:

【中文标题】如何使用多个条件查找查询在 MongoDB 中指定字段?【英文标题】:How to specify fields in MongoDB with multiple condition find query? 【发布时间】:2019-03-15 09:32:00 【问题描述】:

这是单个文档:


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

我正在尝试仅选择 John's BMW 的“carColor”。 像这样的:

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

有什么想法吗?

【问题讨论】:

【参考方案1】:

为什么它不起作用?

"firstName": "John", "cars.carName": "BMW"

表示“名字是 john,并且汽车数组中至少有一个条目,其中 carName 是“BMW””。但它返回完整的文档,没有过滤数组。

"_id": 0, "cars.carColor": 1

不投影_id,而是投影cars数组所有条目的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 有 2 辆 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"
      
    
  
])

【讨论】:

【参考方案2】:
db.persons.find(
  firstName: 'john',
  cars: 
    $elemMatch: 
      carName: 'BMW'
    
  
,

  'cars.$': 1
)

【讨论】:

【参考方案3】:

如果您知道数组中的“BMW”值不超过一个,那么这是一种使用单个$project 阶段获取结果的方法:

db.getCollection('collection').aggregate([
    $match: 
        "firstName": "john"
        /* for performance reasons, you may want to include the following line which, however, is not required */
        /* this makes sense if you have lots of "john"s with different sets of cars in your database */
        , "cars.carName": "BMW" // this will use an index on "cars.carName" if available
    
, 
    $project: 
        _id: 0, // do not return the _id field
        color: 
            $reduce:  // transform the filtered input array
                "input": 
                    $filter:  // remove all non-"BMW" cars from the "cars" array
                        input: "$cars",
                        as: "car",
                        cond:  $eq: [ "$$car.carName", "BMW" ] 
                    
                ,
                "initialValue": null,
                "in": "$$this.carColor" // just return the color value, nothing else
            
        
    
])

【讨论】:

以上是关于如何使用多个条件查找查询在 MongoDB 中指定字段?的主要内容,如果未能解决你的问题,请参考以下文章

mongodb更新查询删除命令中指定的字段以外的所有数组字段

mongodb更新查询删除命令中指定的字段以外的所有数组字段

MongoDB 条件查询和排序

如果满足另一个中指定的条件,则更新查询在其中一个中更新数据

在 Notepad++ 中指定多个目录 在文件中查找

如何在 MySQL 的子查询中指定父查询字段?