【问题标题】:Mongo: $exists in Pipeline $lookup not working as expectedMongo:管道中的 $exists $lookup 未按预期工作
【发布时间】: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"] } } }

标签: mongodb mongodb-query nosql aggregation-framework


【解决方案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 提到的产品变量不存在于管道阶段。有什么想法吗?
    • 有可能。请分享示例输入和预期输出的完整屏蔽版本,以便我提供帮助。
    猜你喜欢
    • 2020-01-01
    • 2022-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多