集約を使用するこれら 3 つの中で最も簡単なのは、交差 ** です。その一般的なケースは、次のような集計を使用して実行できます。
交差点:
db.colors.aggregate([
{'$unwind' : "$left"},
{'$unwind' : "$right"},
{'$project': {
value:"$left",
same:{$cond:[{$eq:["$left","$right"]}, 1, 0]}
}
},
{'$group' : {
_id: {id:'$_id', val:'$value'},
doesMatch:{$max:"$same"}
}
},
{'$match' :{doesMatch:1}},
]);
残りの 2 つはもう少しトリッキーになります。私の知る限り、同じドキュメント内の 2 つの別々のフィールドを組み合わせる方法はありません。$project パイプライン フェーズに $add、$combine、または $addToSet があると便利ですが、これは存在しません。したがって、私たちができる最善のことは、何かが交差したかどうかを言うことです. 両方の集計を次のように開始できます。
db.colors.aggregate([
{'$unwind' : "$left"},
{'$unwind' : "$right"},
{'$project': {
left:"$left",
right:'$right',
same:{$cond:[{$eq:["$left","$right"]}, 1, 0]}
}
},
{'$group' : {
_id:{id:'$_id', left:'$left'},
right:{'$addToSet':'$right'},
sum: {'$sum':'$same'},
}
},
{'$project': {
left:{val:"$_id.left",inter:"$sum"},
right:'$right',
}
},
{'$unwind' : "$right"},
{'$project': {
left:"$left",
right:'$right',
same:{$cond:[{$eq:["$left.val","$right"]}, 1, 0]}
}
},
{'$group' : {
_id:{id:'$_id.id', right:'$right'},
left:{'$addToSet':'$left'},
sum: {'$sum':'$same'},
}
},
{'$project': {
right:{val:"$_id.right",inter:"$sum"},
left:'$left',
}
},
{'$unwind' : "$left"},
{'$group' : {
_id:'$_id.id',
left:{'$addToSet':'$left'},
right: {'$addToSet':'$right'},
}
},
]);
質問で提供されたサンプルを集計すると、次のような結果が得られます。
{
"_id" : 1,
"left" : [
{
"val" : "green",
"inter" : 1
},
{
"val" : "red",
"inter" : 0
}
],
"right" : [
{
"val" : "blue",
"inter" : 0
},
{
"val" : "green",
"inter" : 1
}
]
}
ここから、以下を集計に追加することで交差を取得できます。
{'$project': {
left:"$left"
}
},
{'$unwind' : "$left"},
{'$match' : {'left.inter': 1}},
{'$group' : {
_id:'$_id',
left:{'$addToSet':'$left'},
}
},
ベース集約の最後に以下を追加することで、違いと相対的な補数を見つけることができます。

{'$unwind' : "$left"},
{'$match' : {'left.inter': 0}},
{'$unwind' : "$right"},
{'$match' : {'right.inter': 0}},
{'$group' : {
_id:'$_id',
left:{'$addToSet':'$left'},
right:{'$addToSet':'$right'},
}
},
残念ながら、異なる分野の異なるアイテムを組み合わせる良い方法はないようです。ユニオンを得るには、クライアントからそれを行うのが最善のようです。または、フィルタリングが必要な場合は、各セットで個別に行います。