$ SetUnion MongoDB не работает с массивом массивов, генерируемых $ push - PullRequest
0 голосов
/ 27 августа 2018

Я пытаюсь выполнить сложный запрос агрегации для некоторой коллекции (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")
    ]
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...