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"
.
我需要将来自相同 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"
.