$lookup
を使用して複数の結合条件を実行できます バージョン3.6以降の集約パイプライン演算子。
let
を使用して、フィールドの値を変数に割り当てる必要があります オプションのフィールド。次に、pipeline
でこれらの変数にアクセスします コレクションで実行するパイプラインを指定するフィールドステージ。
$match
に注意してください ステージでは、$expr
を使用します フィールドの値を比較するための評価クエリ演算子。
パイプラインの最後の段階は$replaceRoot
です $lookup
を単純にマージする集約パイプラインステージ $$ROOT
の一部を含む結果 $mergeObjects
を使用したドキュメント オペレーター。
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以降を使用していない場合は、最初にフィールドの1つ(たとえば「user1」)を使用して参加し、そこから$unwind
を使用して一致するドキュメントの配列を巻き戻します。 集約パイプライン演算子。パイプラインの次の段階は$redact
です $$KEEP
を使用して、「joined」コレクションの「user2」の値と入力ドキュメントが等しくないドキュメントを除外するステージ および$$PRUNE
システム変数。その後、$project
でドキュメントの形状を変更できます ステージ。
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
}
コレクション内のドキュメントが同じ構造であり、この操作を頻繁に実行していることに気付いた場合は、2つのコレクションを1つにマージするか、それらのコレクション内のドキュメントを新しいコレクションに挿入することを検討する必要があります。
db.collection3.insertMany(
db.collection1.find({}, {"_id": 0})
.toArray()
.concat(db.collection2.find({}, {"_id": 0}).toArray())
)
次に、$group
「user1」と「user2」によるドキュメント
db.collection3.aggregate([
{ "$group": {
"_id": { "user1": "$user1", "user2": "$user2" },
"percent": { "$push": "$percent" }
}}
])
これにより、次のようになります:
{ "_id" : { "user1" : 1, "user2" : 2 }, "percent" : [ 0.56, 0.3 ] }