为啥在与数组中的字段匹配时,mongoDB聚合中的查找中的管道不起作用?

Posted

技术标签:

【中文标题】为啥在与数组中的字段匹配时,mongoDB聚合中的查找中的管道不起作用?【英文标题】:Why is pipeline inside a lookup in mongoDB aggregation doesn't work when matched with a field in array?为什么在与数组中的字段匹配时,mongoDB聚合中的查找中的管道不起作用? 【发布时间】:2021-03-13 02:14:57 【问题描述】:

我一直试图在 MongoDB 中编写一个聚合管道,它使用带有子管道的查找阶段。在该管道中,我试图将文档中数组中的字段与字符串数组进行匹配。但它似乎不起作用。我得到一个空的结果(没有文件)。

以下是名为“卡片”的集合中的文档:


"_id": "5fbff18be1157d5f8c6089f2",
"keywords": [
    "type": "topic",
    "value": "benny"
  , 
    "type": "tag",
    "value": "bo"
  , 
    "type": "tag",
    "value": "bo"
  ],
"name": "tasty_steel_car"

在此,我尝试将关键字中的字段“值”与以下查询匹配:


 'from': 'cards', 
 'let': 
   'keywordList': '$keywords'
 , 
 'pipeline': [
   
   "$match": 
     "$expr":  
       $and: [
          "$in": [ "$keywords.value", ['benny'] ]  
       ]
      
    
     
  
   
  ], 
 'as': 'cards'

我在这里做错了什么?

以下部分似乎不起作用:

 "$in": [ "$keywords.value", ['benny'] ]  

即使以下方法似乎也不起作用:

db.cards.find( 

  $expr: 
      $in: [ "$keywords.value", ["benny"] ]
  

)

【问题讨论】:

不工作是什么意思? 结果为空 【参考方案1】:

假设您正在尝试查找包含您想要的特定关键字的所有 cards 文档(例如,您的示例中的“benny”), 你可以试试下面的代码:

db.getCollection(<collection name>).aggregate([
    
        $lookup: 
            from: "card",
            let: 
                keywordList: "$keywords"
            ,
            // this pipeline is used to filter only a list with the keyword
            pipeline : [
                
                    $project : 
                        keywords :  
                            $filter:  
                                input: "$keywords", 
                                as: "keyword", 
                                cond: 
                                    $eq : ["$$keyword.value", "benny"]
                                 
                            
                        
                    
                
            ],
            as: "filteredCardLookups"
        
    ,
    
        $addFields : 
            // this will help to filter out card collection lookup that contains no keyword
            filteredCardLookups :  
                $filter:  
                    input: "$filteredCardLookups", 
                    as: "filteredCardLookup", 
                    cond: 
                        $ne : ["$$filteredCardLookup.keywords", []]
                     
                
            
            
    
]);

您的最终结果可能如下所示:


    ...
    "filteredCardLookups" : [ 
        
            "_id" : "5fbff18be1157d5f8c6089f2",
            "keywords" : [ 
                
                    "type" : "topic",
                    "value" : "benny"
                
            ]
        
    ]
    ...

【讨论】:

【参考方案2】:

这里有 2 个不同的地方需要改变。 根据the documentation,$in 采用以下参数:

[ <expression>, <array expression> ]

所以你必须转换你的论点。

第二件事是“benny”不能是一个数组,因为“keywords.value”的每个元素都是一个字符串。

所以查找阶段的良好语法是


    "$lookup": 
      "from": "cards",
      "let": 
        "keywordList": "$keywords.value"
      ,
      "pipeline": [
        
          "$match": 
            "$expr": 
              $and: [
                
                  "$in": [
                    "benny",
                    "$keywords.value"
                  ]
                
              ]
            
          
        
      ],
      "as": "cards"
    
  

You can test it here

【讨论】:

感谢您的回答,但“benny”只是一个示例,我想使用 $keywordList 将其与关键字数组匹配 您要检查什么?如果第一个数组的任何值在第二个数组中?如果所有值都存在?

以上是关于为啥在与数组中的字段匹配时,mongoDB聚合中的查找中的管道不起作用?的主要内容,如果未能解决你的问题,请参考以下文章

如何匹配 MongoDB 中的子文档数组?

Mongodb聚合数组大小大于匹配[重复]

Mongodb聚合数组大小大于匹配[重复]

数组中字段的最小值和数组mongodb聚合查询中的第一个对象

MongoDB 聚合与特定字段不匹配

使用聚合重命名 MongoDB 中的字段