拥有以下两个系列:
// collection1:
{
user1: 1,
user2: 2,
percent: 0.56
}
// collection2:
{
user1: 1,
user2: 2,
percent: 0.3
}
我想在user1
和user2
上加入这两个系列.
如何编写管道以获得如下结果:
{
user1: 1,
user2: 2,
percent1: 0.56,
percent2: 0.3
}
拥有以下两个系列:
// collection1:
{
user1: 1,
user2: 2,
percent: 0.56
}
// collection2:
{
user1: 1,
user2: 2,
percent: 0.3
}
我想在user1
和user2
上加入这两个系列.
如何编写管道以获得如下结果:
{
user1: 1,
user2: 2,
percent1: 0.56,
percent2: 0.3
}
在3.6版及更高版本中,我们可以使用$lookup
聚合管道操作符执行多个连接条件.
我们需要使用let
可选字段将字段的值分配给变量;然后在pipeline
个字段stage中访问这些变量,在这里指定要在集合上运行的管道.
请注意,在$match
阶段,我们使用$expr
求值查询运算符来比较字段的值.
管道中的最后一个阶段是$replaceRoot
聚合管道阶段,我们使用$mergeObjects
操作符简单地将$lookup
结果与$$ROOT
文档的一部分合并.
db.collection2.aggregate([
{
$lookup: {
from: "collection1",
let: {
firstUser: "$user1",
secondUser: "$user2"
},
pipeline: [
{
$match: {
$expr: {
$and: [
{
$eq: [
"$user1",
"$$firstUser"
]
},
{
$eq: [
"$user2",
"$$secondUser"
]
}
]
}
}
}
],
as: "result"
}
},
{
$replaceRoot: {
newRoot: {
$mergeObjects:[
{
$arrayElemAt: [
"$result",
0
]
},
{
percent1: "$$ROOT.percent1"
}
]
}
}
}
]
)
这条管道产生的结果如下所示:
{
"_id" : ObjectId("59e1ad7d36f42d8960c06022"),
"user1" : 1,
"user2" : 2,
"percent" : 0.3,
"percent1" : 0.56
}
如果您不在3.6+版本上,您可以首先使用一个字段(比如"user1")加入,然后使用$unwind
聚合管道操作符从那里释放匹配文档的array.管道中的下一个阶段是$redact
阶段,在该阶段中,使用$$KEEP
和$$PRUNE
系统变量过滤掉"joined"集合中的"user2"值与输入文档不相等的文档.然后,您可以在$project
阶段reshape 文档.
db.collection1.aggregate([
{ "$lookup": {
"from": "collection2",
"localField": "user1",
"foreignField": "user1",
"as": "collection2_doc"
}},
{ "$unwind": "$collection2_doc" },
{ "$redact": {
"$cond": [
{ "$eq": [ "$user2", "$collection2_doc.user2" ] },
"$$KEEP",
"$$PRUNE"
]
}},
{ "$project": {
"user1": 1,
"user2": 1,
"percent1": "$percent",
"percent2": "$collection2_doc.percent"
}}
])
它产生:
{
"_id" : ObjectId("572daa87cc52a841bb292beb"),
"user1" : 1,
"user2" : 2,
"percent1" : 0.56,
"percent2" : 0.3
}
如果集合中的文档具有相同的 struct ,并且发现自己经常执行此操作,则应考虑将两个集合合并为一个集合,或者将这些集合中的文档插入到新集合中.
db.collection3.insertMany(
db.collection1.find({}, {"_id": 0})
.toArray()
.concat(db.collection2.find({}, {"_id": 0}).toArray())
)
然后按"user1"和"user2"输入$group
个文档
db.collection3.aggregate([
{ "$group": {
"_id": { "user1": "$user1", "user2": "$user2" },
"percent": { "$push": "$percent" }
}}
])
由此产生:
{ "_id" : { "user1" : 1, "user2" : 2 }, "percent" : [ 0.56, 0.3 ] }