この集計により、望ましい結果が得られます。
db.posts.aggregate( [
{ $match: { updatedAt: { $gte: 1549786260000 } } },
{ $facet: {
FALSE: [
{ $match: { toggle: false } },
{ $unwind : "$interests" },
{ $group : { _id : { iid: "$interests", pid: "$publisher" }, count: { $sum : 1 } } },
],
TRUE: [
{ $match: { toggle: true, status: "INACTIVE" } },
{ $unwind : "$interests" },
{ $group : { _id : { iid: "$interests", pid: "$publisher" }, count: { $sum : -1 } } },
]
} },
{ $project: { result: { $concatArrays: [ "$FALSE", "$TRUE" ] } } },
{ $unwind: "$result" },
{ $replaceRoot: { newRoot: "$result" } },
{ $group : { _id : "$_id", count: { $sum : "$count" } } },
{ $project:{ _id: 0, iid: "$_id.iid", pid: "$_id.pid", count: 1 } }
] )
[編集追加]
質問投稿からの入力データを使用したクエリからの出力:
{ "count" : 1, "iid" : "INT123", "pid" : "P789" }
{ "count" : 1, "iid" : "INT123", "pid" : "P123" }
{ "count" : 0, "iid" : "INT789", "pid" : "P789" }
{ "count" : 1, "iid" : "INT456", "pid" : "P789" }
このクエリは、異なるアプローチ(コード)で同じ結果を取得します:
db.posts.aggregate( [
{
$match: { updatedAt: { $gte: 1549786260000 } }
},
{
$unwind : "$interests"
},
{
$group : {
_id : {
iid: "$interests",
pid: "$publisher"
},
count: {
$sum: {
$switch: {
branches: [
{ case: { $eq: [ "$toggle", false ] },
then: 1 },
{ case: { $and: [ { $eq: [ "$toggle", true] }, { $eq: [ "$status", "INACTIVE" ] } ] },
then: -1 }
]
}
}
}
}
},
{
$project:{
_id: 0,
iid: "$_id.iid",
pid: "$_id.pid",
count: 1
}
}
] )
[編集追加3]
注:
ファセットクエリは、同じドキュメントセットに対して2つのファセット(TRUEとFALSE)を実行します。これは、2つのクエリが並行して実行されているようなものです。ただし、コードが重複しているだけでなく、ドキュメントをパイプラインに沿って整形して目的の出力を取得するための追加のステージもあります。
2番目のクエリはコードの重複を回避し、集約パイプラインのステージははるかに少なくなります。これは、入力データセットに処理するドキュメントが多数ある場合、パフォーマンスの点で違いがあります。一般に、ステージが少ないということは、ドキュメントの反復が少ないことを意味します(ステージは、前のステージから出力されたドキュメントをスキャンする必要があるため)。