MongoDB Pipeline $lookup 仅在硬编码对象 id 时才有效

问题描述 投票:0回答:1

我在 MongoDB 聚合管道阶段之一遇到了一个奇怪的问题。

以下是上一阶段的结果:

[
  {
    "_id": {
      "$oid": "6532b629454826446d8f399c"
    },
    "title": "Learning"
  }
  // ... more objects
]

当我如下定义下一个 $match 阶段时(使用硬编码的 ObjectID):

{
  from: "characterengagements",
  let: {
    tagId: { $toObjectId: '$$ROOT._id' },
  },
  pipeline: [
    { $match: { tags: ObjectId("6532b629454826446d8f399c") } },
    { $addFields: { testTagId: '$$tagId' } }
  ],
  as: "topCharacters"
}

我从管道中得到以下输出:

请注意:

  • 此文档已正确返回,因为标签数组字段 包含上面指定的对象 ID。
  • testTagId 显示正确的值(与我硬编码的值相同)
[
  {
    "_id": {
      "$oid": "6532b629454826446d8f399c"
    },
    "title": "Learning",
    "topCharacters": [
      {
        "_id": {
          "$oid": "6532d773454826446dd2b967"
        },
        "character": {
          "$oid": "6532b63aacd66daa12860580"
        },
        "createdAt": {
          "$date": "2023-10-20T19:39:31.517Z"
        },
        "tags": [
          {
            "$oid": "6531c7d2fe4908d7ec87a58a"
          },
          {
            "$oid": "6532b5e6454826446d8ed08c"
          },
          {
            "$oid": "6532b629454826446d8f399c"
          },
          {
            "$oid": "6532b62c454826446d8f3de7"
          },
          {
            "$oid": "6532b74a454826446d91056b"
          }
        ],
        "testTagId": {
          "$oid": "6532b629454826446d8f399c"
        }
      }
    ]
  },
  // ... more documents
]

当我不对该值进行硬编码而是尝试使用 $$tagId (如上所示,格式正确)时,就会出现问题:

{
  from: "characterengagements",
  let: {
    tagId: { $toObjectId: '$$ROOT._id' },
  },
  pipeline: [
    { 
      $match: {
        // $$tagId should be the same as the hard coded value above, as shown by adding testTagId to the output from above, however, I get different results.
        tags: '$$tagId'
      } 
    },
    { 
      $addFields: {
        tagIdWas: '$$tagId'
            }
      
    }
  ],
  as: "topCharacters"
}

以上没有返回任何文档。

如果有人之前遇到过这个问题,我将非常感谢您的帮助。

谢谢!

mongodb aggregation-framework
1个回答
0
投票

根据文档,您必须使用

$expr
运算符来访问
$match
阶段中的变量。

{
  from: "characterengagements",
  let: {
    tagId: { $toObjectId: '$$ROOT._id' },
  },
  pipeline: [
    { 
      $match: {
        $expr: {
          $in: [
            "$$tagId",
            "$tags"
          ]
        }
      }
    },
    { 
      $addFields: {
        tagIdWas: '$$tagId'
      }
    }
  ],
  as: "topCharacters"
}

旁注,我认为转换为

ObjectId
似乎没有必要,因为
_id
ObjectId
。您可以简化为:

let: { tagId: "$_id" }

如果您使用 MongoDB 5.0,您可以同时使用

localField
foreignField
与管道

{
  from: "characterengagements",
  localField: "$_id",
  foreignField: "$tags",
  let: { tagId: "$_id" }
  pipeline: [
    { 
      $addFields: {
        tagIdWas: '$$tagId'
      }
    }
  ],
  as: "topCharacters"
}
© www.soinside.com 2019 - 2024. All rights reserved.