Mongodb 具有 'let' 变量的对象查找数组

Mongodb lookup array of objects with 'let' variable

我需要将来自相同 table 'entities' 的实体连接在一起。 本地键是本地实体的 _id。 外键在 'rels' 对象数组中(_id 存储在 rels.r 中)。

当我使用示例 _id 字符串测试 $match 时,查找工作正常。 但是当我尝试使用用 'let' 声明的变量时(它应该使用相同的字符串,只是在一个变量中)它不起作用。

示例数据:

{ // PARENT ENTITY
  "_id":"123", // the local key
  "title":"initialentity",
},
{ // CHILD ENTITY 
  "_id":"456",
  "title":"relatedentity",
  "rels":[
    {
      "r":"123", // the foreign key
      "a":"exampledata-ignorethisfield",
    },
  ]
}

聚合:

[
  { "$lookup": {
    "from": "entities",
    "let": { "id": { $toString: "$_id" }  },
    // "let": { "id": "$_id"  }, // this alternative let doesn't work either
    "pipeline": [
      //{ "$match": { "rels.r": "123" } }, // This test works fine
      { "$match": { "rels.r": "$$id" } }, // But this, using the let variable, doesn't work
      {"$limit": 1}
    ],
    "as": "result"
  }},
  {"$limit": 1}
]

实际输出(结果数组为空):

{ 
  "_id":"123", // the local key
  "title":"initialentity",
  "results": []
},

预期输出(结果数组具有相关对象):

{ 
  "_id":"123", // the local key
  "title":"initialentity",
  "results": [
    {
      "_id":"456",
      "title":"relatedentity",
      "rels":[
        {
          "r":"123", // the foreign key
          "a":"exampledata-ignorethisfield",
        },
      ]
    }
  ]
},

由于将添加的其他条件,我需要它使用此方法(带管道)。

在此先感谢您的帮助。我确定我遗漏了一些明显的东西。我浏览了许多 SO qs 和 mongo 文档,只是无法弄清楚这个。 我也尝试过类似以下的事情但没有成功:

{ "$match": { $expr: { "rels": {"r" : "$$id"} } } }, // This doesn't work (returns unrelated entities)
{ "$match": { $expr: { $eq: [ "rels.r" , "$$id" ] } } }, // This doesn't work (returns empty array)

您需要使用 $expr as you've tried in order to access the variable $$id, but you also need to prefix rels.r with a $ 以便它比较 rels.r$$id 的值而不是文字字符串 "rels.r".

[
  { "$lookup": {
    "from": "entities",
    "let": { "id": { $toString: "$_id" }  },
    "pipeline": [
      { "$match": { $expr: { $eq: [ "$rels.r" , "$$id" ] } } },
      { "$limit": 1 }
    ],
    "as": "result"
  }},
  { "$limit": 1 }
]

编辑

$eq 如果你匹配一组对象,它似乎不起作用,我已经能够使用 $in:

让它工作
[
  { "$lookup": {
    "from": "entities",
    "let": { "id": { $toString: "$_id" }  },
    "pipeline": [
      { "$match": { $expr: { $in: [ "$$id" , { $ifNull: [ "$rels.r", [] ] } ] } } },
      { "$limit": 1 }
    ],
    "as": "result"
  }},
  { "$limit": 1 }
]

我选择包含 $ifNull 是因为如果第二个参数未解析为数组,$in 将失败,如果文档没有 [=23],则会发生这种情况=] 字段。如果每个文档 确实 有一个 rels 字段,请随意忽略它而只使用 "$rels.r".

Working MongoPlayground