2015-10-27 3 views
2

У меня есть коллекция компаний, которая выглядит так. Я также хочу объединить другие документы. мне это нужно:Возвращает массив элементов из нескольких массивов

{ 
    "_id" : ObjectId("561637942d25a7644cae993e"), 
    "locations" : [ 
     { 
      "deals" : [ 
       { 
        "name" : "1", 
        "_id" : ObjectId("561637942d25a7644cae9940") 
       }, 
       { 
        "name" : "2", 
        "_id" : ObjectId("562f868ce73962c626a16b15") 
       } 
      ] 
     } 
    ], 
    "deals" : [ 
     { 
      "name" : "3", 
      "_id" : ObjectId("562f86ebe73962c626a16b17") 
     } 
    ] 
} 
{ 
    "_id" : ObjectId("561637942d25a7644cae993e"), 
    "locations" : [ 
     { 
      "deals" : [ 
       { 
        "name" : "4", 
        "_id" : ObjectId("561637942d25a7644cae9940") 
       } 
      ] 
     } 
    ], 
    "deals" : [] 
} 

Чтобы быть похожим на это:

{ 
    "deals": [{ 
     "name" : "1", 
     "_id" : ObjectId("561637942d25a7644cae9940") 
    },{ 
     "name" : "2", 
     "_id" : ObjectId("562f868ce73962c626a16b15") 
    },{ 
     "name" : "3", 
     "_id" : ObjectId("562f86ebe73962c626a16b17") 
    },{ 
     "name" : "4", 
     "_id" : ObjectId("561637942d25a7644cae9949") 
    }] 
} 

Но я только не сделал этого. Похоже, если я хочу, чтобы все сделки были сгруппированы в один массив, я не должен использовать unind, так как это создает больше документов, потому что мне нужно только один раз группировать. Это моя попытка, которая не работает вообще.

{ 
       "$project": { 
        "_id": 1, 
        "locations": 1, 
        "deals": 1 
       } 
      }, { 
       "$unwind": "$locations" 
      }, { 
       "$unwind": "$locations.deals" 
      }, { 
       "$unwind": "$deals" 
      }, { 
       "$group": { 
        "_id": null, 
        "deals": { 
         "$addToSet": "$locations.deals", 
         "$addToSet": "$deals" 
        } 
       } 
      } 

ответ

1

Вы должны сначала использовать фильтр документов, чтобы уменьшить размер документов для обработки в трубопроводе с помощью оператора $match. Затем нам понадобится $unwind массив «местоположения», после которого мы используем оператор $project для изменения ваших документов. Оператор $cond используется для возврата одного массива элементов [false], если поле deals пустое или значение deals, потому что пустой пул будет вызывать исключение. Конечно, оператор $setUnion возвращает массив элементов, которые появляются в массиве locations.deals или в массиве deals. Затем мы используем оператор $setDifference для фильтрации элемента false из объединенного массива. Затем нам нужен еще один этап $unwind, где мы деконструируем массив deals. Оттуда вы можете легко получить ваши документы.

db.collection.aggregate([ 
    { "$match": { "locations.0": { "$exists": true } } }, 
    { "$unwind": "$locations" }, 
    { "$project": { 
     "deals": { 
      "$setDifference": [ 
       { "$setUnion": [ 
        { "$cond": [ 
         { "$eq" : [ { "$size": "$deals" }, 0 ] }, 
         [false], 
         "$deals" 
        ]}, 
        "$locations.deals" 
       ]}, 
       [false] 
      ] 
     } 
    }}, 
    { "$unwind": "$deals" }, 
    { "$group": { 
     "_id": null, 
     "deals": { "$addToSet": "$deals" } 
    }} 
]) 

Который возвращает:

{ 
     "_id" : null, 
     "deals" : [ 
       { 
         "name" : "1", 
         "_id" : ObjectId("561637942d25a7644cae9940") 
       }, 
       { 
         "name" : "2", 
         "_id" : ObjectId("562f868ce73962c626a16b15") 
       }, 
       { 
         "name" : "3", 
         "_id" : ObjectId("562f86ebe73962c626a16b17") 
       }, 
       { 
         "name" : "4", 
         "_id" : ObjectId("561637942d25a7644cae9940") 
       } 
     ] 
}