我正在试用MongoDb 3.5.8中提供的新$lookup
pipeline
功能,并想知道如何从pipeline
引用父文档中的字段。
我试图将父文档中的两个字段与查找文档中的两个字段进行比较。不确定如何执行此操作{$eq : ['$input_doc.field1', '$field1'] }
。
db.input_doc.aggregate([
{
$lookup:
{
from: "foreign_doc",
pipeline: [
{ $project: { 'matched': { $and : [
{ $eq : ["$input_doc.field1", "$field1"] },
{ $eq : ["$input_doc.field2", "$field2"] }
]} },
{ $match : { 'matched' : true } }
],
as: "as_doc"
}
}
])
谢谢
答案 0 :(得分:1)
这里不清楚你的意思,你可能意味着将let
与新的pipeline
选项一起使用,但它也可能意味着一个完全不同的情况
pipeline
操作通常用于"非关联"数据检索,在各种用例中都很有用。这与"相关"相反。可以将localField
和foreignField
应用于"加入"的数据两个集合之间。
如上所述,DOCS-10298
涵盖了这一点最佳示范作为一个例子。创建这些集合:
db.related.insert([
{ "a": 1, "b": 2 },
{ "a": 2, "b": 2 },
{ "a": 3, "b": 3 }
])
db.parent.insert({
"name": "test",
"b": 2
})
我可以在这里使用pipeline
和let
语句来测试其他集合的项目的逻辑条件,如下所示:
db.parent.aggregate([
{ "$lookup": {
"from": "related",
"let": {
"b": "$b"
},
"pipeline": [
{ "$addFields": {
"matched": { "$eq": [ "$$b", "$b" ] }
}}
],
"as": "results"
}}
])
将给出结果:
{
"_id" : ObjectId("595332c28965d862ce61f451"),
"name" : "test",
"b" : 2,
"results" : [
{
"_id" : ObjectId("59532b028965d862ce61f44d"),
"a" : 1,
"b" : 2,
"matched" : true
},
{
"_id" : ObjectId("59532b028965d862ce61f44e"),
"a" : 2,
"b" : 2,
"matched" : true
},
{
"_id" : ObjectId("59532b028965d862ce61f44f"),
"a" : 3,
"b" : 3,
"matched" : false
}
]
}
这表明条件是针对来自父文档的let
中的声明变量与来自pipeline
中提供的相关集合的变量进行测试的。
这允许你也使用"逻辑"过滤器,例如$redact
:
db.parent.aggregate([
{ "$lookup": {
"from": "related",
"let": {
"b": "$b"
},
"pipeline": [
{ "$redact": {
"$cond": {
"if": { "$eq": [ "$$b", "$b" ] },
"then": "$$KEEP",
"else": "$$PRUNE"
}
}}
],
"as": "results"
}}
])
返回:
{
"_id" : ObjectId("595332c28965d862ce61f451"),
"name" : "test",
"b" : 2,
"results" : [
{
"_id" : ObjectId("59532b028965d862ce61f44d"),
"a" : 1,
"b" : 2
},
{
"_id" : ObjectId("59532b028965d862ce61f44e"),
"a" : 2,
"b" : 2
}
]
}
但是,当然,MongoDB 3.2中引入的现有功能已经涵盖了正常的"相关的"选项:
db.parent.aggregate([
{ "$lookup": {
"from": "related",
"localField": "b",
"foreignField": "b",
"as": "results"
}}
])
与上述结果相同。
当然,如果您需要"附加条件",那么使用$unwind
和$match
进行写作效率最高:
db.parent.aggregate([
{ "$lookup": {
"from": "related",
"localField": "b",
"foreignField": "b",
"as": "results"
}},
{ "$unwind": "$results" },
{ "$match": { "results.a": 1 } }
])
这是因为$lookup
之后的以下阶段的汇总管道选项实际上是#34;悬挂"进入$lookup
操作本身。在"解释"中展示输出:
{
"$lookup" : {
"from" : "related",
"as" : "results",
"localField" : "b",
"foreignField" : "b",
"unwinding" : {
"preserveNullAndEmptyArrays" : false
},
"matching" : {
"a" : {
"$eq" : 1
}
}
}
}
这显示"展开"的选项和#34;匹配"实际上已在$lookup
内应用。到目前为止,您不能直接编写它,但管道组合会应用此行为。
事实上,这基本上是因为创建一个条目超过16MB上限的数组而没有被破坏的BSON限制。
简而言之,在大多数情况下,您通常需要现有行为,而不需要新选项。爱好。