Вы можете использовать ниже агрегации:
db.col.aggregate([
{
$group: {
_id: "$key",
docs: { $push: "$$ROOT" },
lastId: { $last: "$_id" }
}
},
{
$project: {
_id: 1,
lastId: 1,
original: { $arrayElemAt: [ { $filter: { input: "$docs", as: "d", cond: { $eq: [ "$$d.set", "original" ] } } } , 0 ] },
modified: { $arrayElemAt: [ { $filter: { input: "$docs", as: "d", cond: { $eq: [ "$$d.set", "modified" ] } } } , 0 ] }
}
},
{
$project: {
_id: 1,
lastId: 1,
state: {
$switch: {
branches: [
{ case: { $eq: [ "$original", undefined ] }, then: "created" },
{ case: { $eq: [ "$modified", undefined ] }, then: "deleted" },
{ case: { $ne: [ "$modified.element", "$original.element" ] }, then: "changed" }
],
default: "notModified"
}
}
}
},
{
$group: {
_id: "$state",
ids: { $push: "$lastId" }
}
},
{
$match: {
_id: { $ne: "notModified" }
}
},
{
$group: {
_id: null,
stats: { $push: { k: "$_id", v: "$ids" } }
}
},
{
$replaceRoot: {
newRoot: {
$arrayToObject: "$stats"
}
}
}
])
Изначально вам нужно использовать $ group с $ filter , чтобы получить modified
и original
полей на key
. Затем вы можете использовать $ switch для определения состояния на основе этих двух полей. Наконец, вы можете снова $group
(этим state
) и использовать $ arrayToObject с операторами $ replaceRoot для динамического получения ключей на основе обнаруженных состояний. Конечный результат:
{ "deleted" : [ 3 ], "changed" : [ 5 ], "created" : [ 6 ] }
РЕДАКТИРОВАТЬ: В качестве альтернативы вы можете получить один документ на ключ, используя агрегацию ниже:
db.col.aggregate([
{
$group: {
_id: "$key",
docs: { $push: "$$ROOT" },
lastId: { $last: "$_id" }
}
},
{
$project: {
_id: 1,
lastId: 1,
original: { $arrayElemAt: [ { $filter: { input: "$docs", as: "d", cond: { $eq: [ "$$d.set", "original" ] } } } , 0 ] },
modified: { $arrayElemAt: [ { $filter: { input: "$docs", as: "d", cond: { $eq: [ "$$d.set", "modified" ] } } } , 0 ] }
}
},
{
$project: {
_id: 1,
lastId: 1,
state: {
$switch: {
branches: [
{ case: { $eq: [ "$original", undefined ] }, then: "created" },
{ case: { $eq: [ "$modified", undefined ] }, then: "deleted" },
{ case: { $ne: [ "$modified.element", "$original.element" ] }, then: "changed" }
],
default: "notModified"
}
}
}
},
{
$match: {
state: { $ne: "notModified" }
}
},
{
$project: {
_id: "$lastId",
state: 1
}
}
])
выходы: * * тысяча двадцать-пять
{ "state" : "created", "_id" : 6 }
{ "state" : "changed", "_id" : 5 }
{ "state" : "deleted", "_id" : 3 }