Как объединить два отдельных агрегата в один и тот же результат

Я хочу взять две агрегации и объединить их вместе. "Blakes Seven" любезно помог мне с парой запросов получить первые и вторые значения элементов массива, но мне нужно два вместе.

Первый:

db.getCollection('anothertest').aggregate([
{ "$unwind": "$a" },
{ "$group": {
    "_id": "$_id",
    "first": { "$first": "$a" }
}}
])

Дайте результат:

{
"result" : [ 
    {
        "_id" : ObjectId("565cc5261506995581569439"),
        "first" : 4
    }
],
"ok" : 1.0000000000000000
}

Второй:

db.getCollection('anothertest').aggregate([
{ "$unwind": "$a" },
// Keeps the first element
{ "$group": {
    "_id": "$_id",
    "first": { "$first": "$a" },
    "a": { "$push": "$a" }
 }},
{ "$unwind": "$a" }
,
// Removes the first element
{ "$redact": {
"$cond":{
"if": { "$ne": [ "$first", "$a" ] },
"then": "$$KEEP",
  "else": "$$PRUNE"
}
}}

Дает результат:

{
"result" : [ 
    {
        "_id" : ObjectId("565cc5261506995581569439"),
        "second" : 2
    }
],
"ok" : 1.0000000000000000
}

Что мне нужно, это результат:

{
"result" : [ 
    {
        "_id" : ObjectId("565cc5261506995581569439"),
        "first" : 4
        "second" : 2
    }
],
"ok" : 1.0000000000000000
}

В дополнение к этому документ, на котором он основан, является просто примером, в котором значения находятся как элементы в массиве. Как бы я использовал это на вложенном массиве? Если все это сложно для агрегации, может быть, есть более простой способ добиться этого с помощью Map Reduce? Спасибо за любую помощь.

Документ для вышеупомянутого ниже:

{
"_id" : ObjectId("565cc5261506995581569439"),
"a" : [ 
    4, 
    2, 
    8, 
    71, 
    21
]
}

ОБНОВЛЕНИЕ К МОЕМУ ОРИГИНАЛЬНОМУ ПОСТУ. Теперь мне удалось взять потрясающий сценарий и заставить его работать для моего документа, который имеет вложенные массивы - до определенного момента.

{ "$match": {objectOriginAPI : "Profit & Loss"}},
{ "$unwind": "$objectRawOriginData.Reports" },
        { "$unwind": "$objectRawOriginData.Reports.Rows" },
        { "$unwind": "$objectRawOriginData.Reports.Rows.Rows" },
        { "$unwind": "$objectRawOriginData.Reports.Rows.Rows.Cells" },
{ "$group": {
    "_id": "$_id",
    "first": { "$first": "$objectRawOriginData.Reports.Rows.Rows.Cells.Value" },
    "a": { "$push": "$objectRawOriginData.Reports.Rows.Rows.Cells.Value" }
}},
{ "$unwind": "$a" },
{"$skip":1},
{ "$group": {
    "_id": "$_id",
    "BalanceName": { "$first": "$first" },
    "BalanceValue": { "$first":      "$objectRawOriginData.Reports.Rows.Rows.Cells.Value" },
}}
])

На самом деле, я случайно забыл обновить второй $unwind, чтобы он оставался как "$a". и что случилось, я получил следующий результат:

{
"result" : [ 
    {
        "_id" : ObjectId("564d12da1506995581569428"),
        "BalanceName" : "Sales",
        "BalanceValue" : null
    }
],
"ok" : 1.0000000000000000
}

Но когда я изменил $unwind, чтобы он соответствовал $unwind для первого значения, я не получил никаких результатов. Я не могу понять, почему, какие-либо идеи? Спасибо Мэтт

1 ответ

Решение

Вы можете сделать это, следуя той же логике, что и первое опубликованное вами агрегирование. Обратите внимание, что я использовал $ skip, чтобы пропустить первый элемент массива и получить второй.

db.collection.aggregate([
    { "$match": {
        "_id": ObjectId("565cc5261506995581569439")
    }},
    { "$unwind": "$a" },
    { "$group": {
        "_id": "$_id",
        "first": { "$first": "$a" },
        "a": { "$push": "$a" }
    }},
    { "$unwind": "$a" },
    {"$skip":1},
    { "$group": {
        "_id": "$_id",
        "first": { "$first": "$first" },
        "second": { "$first": "$a" },
    }}
])

Результат:

{ 
    "_id" : ObjectId("565cc5261506995581569439"),
    "first" : 4,
    "second" : 2 
}

Ваша вторая агрегация также довольно близка к желаемому результату:

db.collection.aggregate([
    { "$match": {
        "_id": ObjectId("565cc5261506995581569439")
    }},
    { "$unwind": "$a" },
    { "$group": {
        "_id": "$_id",
        "first": { "$first": "$a" },
        "a": { "$push": "$a" }
    }},
    { "$unwind": "$a" },
    { "$redact": {
        "$cond":{
        "if": { "$ne": [ "$first", "$a" ] },
            "then": "$$KEEP",
            "else": "$$PRUNE"
    }}},
    { "$limit": 1},
    { "$project": {
        "_id":1,
        "first":1,
        "second":"$a"
    }}
])

РЕДАКТИРОВАТЬ: Кроме того, так как они оба агрегации работают только для одного документа, поэтому необходимо добавить начальный шаг $ match.

Другие вопросы по тегам