Как объединить два отдельных агрегата в один и тот же результат
Я хочу взять две агрегации и объединить их вместе. "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.