Как объединить результаты двух запросов конвейера агрегации MongoDB и выполнить другой запрос агрегации для объединенного результата без использования $ фасета? - PullRequest
1 голос
/ 13 июля 2020

Мой первый запрос возвращает следующий результат после различных этапов конвейера агрегации:

{ 
    "group" : "A",
    "count" : 6, 
    "total" : 20
},
{
    "group" : "B",
    "count" : 2,
    "total" : 50
}

Мой второй запрос возвращает следующий результат после различных этапов конвейера агрегации:

{
    "group": "A",
    "count": 4,
    "total": 80
},
{
    "group": "C",
    "count": 12,
    "total": 60
}

Оба запроса выполняются для одной и той же коллекции, но группирует и преобразует данные по-разному в зависимости от этапов конвейера.

Оба моих запроса используют разные условия $match, имеют разные этапы конвейера, включая $facet,$unwind,$group,$project и такие операторы, как $map,$reduce,$zip,$subtract ...

db.collection.aggregate([
{ $unwind...},
{ $match....},
{ $facet...},
...
])

Когда я использую $facet для выполнения моих запросов как параллельных запросов, возникает следующая ошибка (потому что я ' m уже использует $facet в моих существующих запросах):

$facet is not allowed to be used within a $facet stage

Ожидаемый результат:

Мне нужно найти среднее значение для каждой группы.

Для этого мне нужно объединить результаты обоих запросов и выполнить запросы по объединенному результату.

Мой объединенный этап должен выглядеть так:

{ 
    "group" : "A",
    "count" : 10, 
    "total" : 100 
},
{
    "group" : "B",
    "count" : 2,
    "total" : 50
},
{
    "group": "C",
    "count": 12,
    "total": 60
}

Ожидается окончательный результат со средним значением для каждой группы:

{
    "group" : "A",
     "avg" : 10 
},
{
    "group" : "B",
    "avg" : 25
},
{
    "group": "C",
    "avg": 5
}

Существуют ли какие-либо операторы в конвейере агрегации MongoDB для достижения этого без изменения моих существующих запросов?

Как достичь этого варианта использования?

Спасибо!

Ответы [ 2 ]

2 голосов
/ 13 июля 2020

Вы можете запускать свои запросы отдельно, используя $ фасет , а затем использовать приведенное ниже преобразование в $group объединенные результаты на group и вычислить среднее значение:

db.collection.aggregate([
    {
        $facet: {
            first: [ { $match: { "_": true } } ], // your first query
            second: [ { $match: { "_": false } } ], // your second query
        }
    },
    {
        $project: {
            all: {
                $concatArrays: [ "$first", "$second" ]
            }
        }
    },
    {
        $unwind: "$all"
    },
    {
        $group: {
            _id: "$all.group",
            count: { $sum: "$all.count" },
            total: { $sum: "$all.total" },
        }
    },
    {
        $project: {
            _id: 0,
            group: "$_id",
            count: 1,
            total: 1,
            avg: { $divide: [ "$total", "$count" ] }
        }
    }
])

Пн go Площадка

Примечание. Я использую символ _, чтобы указать, из какого запроса был получен документ. Очевидно, вам это не нужно, и вы можете заменить $facet запросы на свои

0 голосов
/ 14 июля 2020

Существуют разные подходы к объединению результатов, включая $ merge , который был представлен в 4.2

Но я использовал следующий подход, так как я использую версию 4.0

Сохраните оба результата запроса агрегации в переменную, а затем вставьте ее в новую временную коллекцию:

var result  = db.collection.aggregate(...); //query1 here
db.temp.insert(result.toArray());

var result  = db.collection.aggregate(...); //query2 here
db.temp.insert(result.toArray());

// Find out average
db.temp.aggregate([
    {
        $group: {
            _id: "$group",
            count: { $sum: "$count" },
            total: { $sum: "$total" }
        }
    },
    {
        $project: {
            _id: 0,
            group: "$_id",
            avg: { $divide: [ "$total", "$count" ] }
        }
    }
]).pretty()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...