Node.js 按对象中已存在的数据进行查询
我正在编写一个查询,根据“coll1”中的数据从“coll2”获取数据 Coll1具有以下数据结构:Node.js 按对象中已存在的数据进行查询,node.js,mongodb,aggregation-framework,Node.js,Mongodb,Aggregation Framework,我正在编写一个查询,根据“coll1”中的数据从“coll2”获取数据 Coll1具有以下数据结构: { "_id": "asdf", "name": "John", "bags": [ { "type": "typ1", "size": "siz1" }, { "type": "typ2", "size": "siz2" } ] } { _id: "qwer", coll1Name
{
"_id": "asdf",
"name": "John",
"bags": [
{
"type": "typ1",
"size": "siz1"
},
{
"type": "typ2",
"size": "siz2"
}
]
}
{
_id: "qwer",
coll1Name: "John",
types: ["typ1", "typ3"],
sizes: ["siz1", "siz4"]
}
{
_id: "zxcv",
coll1Name: "John",
types: ["typ2", "typ3"],
sizes: ["siz1", "siz2"]
}
{
_id: "fghj",
coll1Name: "John",
types: ["typ2", "typ3"],
sizes: ["siz1", "siz4"]
}
Coll2具有以下数据结构:
{
"_id": "asdf",
"name": "John",
"bags": [
{
"type": "typ1",
"size": "siz1"
},
{
"type": "typ2",
"size": "siz2"
}
]
}
{
_id: "qwer",
coll1Name: "John",
types: ["typ1", "typ3"],
sizes: ["siz1", "siz4"]
}
{
_id: "zxcv",
coll1Name: "John",
types: ["typ2", "typ3"],
sizes: ["siz1", "siz2"]
}
{
_id: "fghj",
coll1Name: "John",
types: ["typ2", "typ3"],
sizes: ["siz1", "siz4"]
}
我想使用聚合管道的$lookup
阶段获取coll2中与coll1中具有相同类型+大小组合的所有文档。我知道这可以通过使用$lookup pipeline
和$expr
实现,但我似乎不知道如何动态地进行查询以传递到$match
阶段
对于上述数据,我希望得到的输出是:
{
_id: "qwer",
coll1Name: "John",
types: ["typ1", "typ3"],
sizes: ["siz1", "siz4"]
}
{
_id: "zxcv",
coll1Name: "John",
types: ["typ2", "typ3"],
sizes: ["siz1", "siz2"]
}
您可以使用从Col2
获取数据。然后需要检查Col2
()中是否有与Col1
匹配的元素。可以在这里使用。然后,您只需要使用
您使用管道字段过滤管道中的输入文档的方法是正确的 表达式通常应如下所示
"$expr": {
"$and": [
{ "$eq": [ "$name", "$$coll1_name" ] },
{ "$setEquals": [ "$bags.type", "$$types" ] },
{ "$setEquals": [ "$bags.size", "$$sizes" ] }
]
}
其中,条件{“$eq”:[“$name”,“$$coll1_name”]}
中的第一个匹配表达式检查coll1
集合中的name
字段是否与coll2
输入文档中的coll1Name
字段匹配。
当然,应该在管道中的变量中定义coll2
中的字段,并使用let
字段让管道访问这些字段
其他匹配过滤器基本上是检查数组是否相等,例如,“$bags.type”
从coll1
解析为类型的数组,即[“typ1”、“typ3”]
从恰巧是一个数组的获取输出字段时,您可以过滤该数组字段上coll2
中的文档,其中可能有一些空列表作为上述管道$match过滤器的结果:
{ "$match": { "coll1Data.0": { "$exists": true } } }
总体而言,您的聚合管道操作如下所示:
db.getCollection('coll2').aggregate([
{ "$lookup" : {
"from": "coll1",
"let": { "coll1_name": "$coll1Name", "types": "$types", "sizes": "$sizes" },
"pipeline": [
{ "$match": {
"$expr": {
"$and": [
{ "$eq": [ "$name", "$$coll1_name" ] },
{ "$setEquals": [ "$bags.type", "$$types" ] },
{ "$setEquals": [ "$bags.size", "$$sizes" ] }
]
}
} }
],
"as": "coll1Data"
} },
{ "$match": { "coll1Data.0": { "$exists": true } } },
{ "$project": { "coll1Data": 0 } }
])
谢谢你的信息!我正在尝试从coll1中查找coll2,不用担心。查找实际上是双向的,但上述管道的输出与预期/期望的匹配,当然,除非您想在coll1
中进行一些预先筛选,也可以在$lookup
管道中进行筛选。谢谢!这是一个很好的解决方案,尽管不是最有效的。我试图只获取所需的文档,而不是获取超过所需的文档,然后对其进行过滤。