Mongo:管道中的 $exists $lookup 未按预期工作

Posted

技术标签:

【中文标题】Mongo:管道中的 $exists $lookup 未按预期工作【英文标题】:Mongo: $exists in Pipeline $lookup not working as expected 【发布时间】:2021-07-29 15:35:02 【问题描述】:

我的两个系列是:


产品类别


    "_id" : ObjectId("5fca496b61e8a83e5cd0fb01"),
    "category_id" : "1",
    ...


产品


    "_id" : ObjectId("60684610f8f81d0013ce776d"),
    "primary_parent_category" : "1653",
    ...


在$lookup中使用localfield和foreignfield,可以达到预期的效果。

db.getCollection('product_category').aggregate([
    
    "$lookup": 
        "from": "product",
        "localField": "category_id",
        "foreignField": "primary_parent_category",
        "as": "products"
    
    ,
//      "$match":  "products":  $exists: true, $not:  $size: 0   ,
     "$match":  "products":  $exists: true, $ne: []  ,
    
    "$project":
        "child_categories": 0,
        "featured_products": 0,
        "related_brands": 0,
        "child_category_names": 0
    
    
])

以上工作正常,但我必须在 $lookup 中使用管道模型来处理另一个用例(用于添加 $geoNear)。聚合查询如下。

db.getCollection('product_category').aggregate([
    
    "$lookup": 
        "from": "product",
        "let":  "category_id": "$category_id" ,
        "pipeline": [
              "$match":  "product":  $exists: true, $ne: []  ,      
             
                 "$project":
                     "child_categories": 0,
                     "featured_products": 0,
                     "related_brands": 0,
                     "child_category_names": 0
                 
             
        ],
        "as": "products"
    
    
])

这没有按预期工作并返回大量条目。 $match 中的 $exists 未正确执行。 任何帮助表示赞赏。提前致谢。

【问题讨论】:

lookup 中的 $match pipeline 期望 product 字段存在,我怀疑它存在。另外,我看不到 category_id 的比较 您错过了管道中 category_id 的匹配条件, $match: $expr: $eq: ["$$category_id", "$primary_parent_category"] 【参考方案1】:

正确的方法是结合@hhharsha36 和@turivishal 提到的内容。我不得不在 $lookup 块之后移动 $exist 的匹配查询,变量映射匹配块完好无损。

db.getCollection('product_category').aggregate([
  
    "$lookup": 
      "from": "product",
      "let":  "category_id": "$category_id" ,
      "pipeline": [
    
      "$match": 
        "$expr": 
           "$eq": [ "$primary_parent_category",  "$$category_id" ] ,
      ,
    
      "$project":
          "child_categories": 0,
          "featured_products": 0,
          "related_brands": 0,
          "child_category_names": 0
      
    
      ],
      "as": "products"
    
  ,
   "$match": 
       "products": 
       
          "$exists": true,
          "$ne": [],
       
       
   ,
])

【讨论】:

【参考方案2】:

正如@turivishal 所指出的,您必须在管道参数中的$match 内使用$expr 运算符。您必须在尝试使用 $$ 引用临时 MongoDB 变量的任何地方执行此操作。


  $match: 
    
      $expr: "$eq": ["$$<VAR-NAME-IN-LET>", "$<FOREIGN-KEY-IN-TARGET-COL>"]
    
  

db.getCollection('product_category').aggregate([
  
    "$lookup": 
      "from": "product",
      "let":  "category_id": "$category_id" ,
      "pipeline": [
        
          "$match": 
            "$expr": 
               $eq: [ "$primary_parent_category",  "$$category_id" ] ,
            
            "product":  
              $exists: true,
              $ne: [],
            ,
          
        ,      
        
          "$project":
              "child_categories": 0,
              "featured_products": 0,
              "related_brands": 0,
              "child_category_names": 0
          
        
      ],
      "as": "products"
    
  
])

【讨论】:

hhharsha36 turivishal sidgate 感谢您的回复。我试过这个方法,但它仍然返回很多记录。事实上,这种行为就像第一个查询具有 localfield 和 foreignfield 并省略了 match 语句。我怀疑这种行为可能是由于 sidgate 提到的产品变量不存在于管道阶段。有什么想法吗? 有可能。请分享示例输入和预期输出的完整屏蔽版本,以便我提供帮助。

以上是关于Mongo:管道中的 $exists $lookup 未按预期工作的主要内容,如果未能解决你的问题,请参考以下文章

mongo 进阶之——聚合管道

mongo 进阶之——聚合管道

Mongo:$exists 字段的索引

常用操作和管道

为啥 os.path.exists() 会阻止 Windows 命名管道连接?

通过 mongo 聚合管道使用 $match 两次