Я пытаюсь выполнить сложный запрос агрегации для некоторой коллекции (MongoDB 3.4).В этой агрегации мне нужно избавиться от дубликатов, и для этого я хочу использовать оператор $setUnion
.
Пожалуйста, учтите следующее:
const a = ObjectId();
const b = ObjectId();
const c = ObjectId();
const d = ObjectId();
db.getCollection('test').insertMany([
{
arr: [a, b]
},
{
arr: [a, b, c]
},
{
arr: [d]
},
{
arr: [a, d]
}
])
Теперь я выполняюэта агрегация:
db.getCollection('test').aggregate([
{
$group: {
_id: null,
dups: {$push: '$arr'}
}
},
{
$project: {
_id: 0,
noDupsDoesNotWork: {
$setUnion: '$dups'
}
}
}
])
и получение:
{
"noDupsDoesNotWork" : [
[
ObjectId("5b839b38f6db291c78201c0d"),
ObjectId("5b839b38f6db291c78201c0e")
],
[
ObjectId("5b839b38f6db291c78201c0d"),
ObjectId("5b839b38f6db291c78201c0e"),
ObjectId("5b839b38f6db291c78201c0f")
],
[
ObjectId("5b839b38f6db291c78201c0d"),
ObjectId("5b839b38f6db291c78201c10")
],
[
ObjectId("5b839b38f6db291c78201c10")
]
]
}
Что я не понимаю, так как говорят, что $setUnion
работает с массивоммассивы.В моем примере я ожидаю, что он выполнит объединение множеств на 4 массивах.Однако, если я выполню этот запрос агрегации:
db.getCollection('test').aggregate([
{
$group: {
_id: null,
dups: {$push: '$arr'}
}
},
{
$project: {
_id: 0,
flattened: {
$reduce: {
input: '$dups',
initialValue: [],
in: {$concatArrays: ['$$value', '$$this']}
}
}
}
},
{
$project: {
noDups: {$setUnion: '$flattened'}
}
}
])
Тогда я получу ожидаемый результат:
{
"noDups" : [
ObjectId("5b839b38f6db291c78201c0d"),
ObjectId("5b839b38f6db291c78201c0e"),
ObjectId("5b839b38f6db291c78201c0f"),
ObjectId("5b839b38f6db291c78201c10")
]
}
Но на этот раз $setUnion
работает на одном массиве объектов, ине массив массивов.
Я тем более озадачен, поскольку, если я явно пропущу четыре подмассива, я получу ожидаемый результат:
db.getCollection('test').aggregate([
{
$group: {
_id: null,
dups: {$push: '$arr'}
}
},
{
$project: {
_id: 0,
explicit: {
$setUnion: [
{$arrayElemAt: ['$dups', 0]},
{$arrayElemAt: ['$dups', 1]},
{$arrayElemAt: ['$dups', 2]},
{$arrayElemAt: ['$dups', 3]},
]
}
}
}
])
Чего мне здесь не хватает?
Для ясности это желаемый результат (подробно описано выше, но добавлен еще раз):
{
"noDups" : [
ObjectId("5b839b38f6db291c78201c0d"),
ObjectId("5b839b38f6db291c78201c0e"),
ObjectId("5b839b38f6db291c78201c0f"),
ObjectId("5b839b38f6db291c78201c10")
]
}