Mongodb поиск массив элементов с объединенным результатом - PullRequest
1 голос
/ 18 марта 2020

Итак, это мои два документа

Документ заказа:

{
   "_id":"02a33b9a-284c-4869-885e-d46981fdd679",
   "context":{
      "products":[
         {
         "id": "e68fc86a-b4ad-4588-b182-ae9ee3db25e4",
         "version": "2020-03-14T13:18:41.296+00:00"
         }
      ],
   },
}

Документ продукта:

{
   "_id":"e68fc86a-b4ad-4588-b182-ae9ee3db25e4",
   "context":{
      "name": "My Product",
      "image": "someimage"
   },
}

Итак, я пытаюсь найти продукты в заказе, но результат должен содержать комбинированные поля, например:

"products":[
             {
             "_id": "e68fc86a-b4ad-4588-b182-ae9ee3db25e4",
             "version": "2020-03-14T13:18:41.296+00:00",
             "name": "My Product",
             "image": "someimage"
             }
          ],

Не знаете, как это сделать, должен ли я делать это вне поиска или внутри? Это моя агрегация

Orders.aggregate([
{
   "$lookup":{
      "from":"products",
      "let":{
         "products":"$context.products"
      },
      "pipeline":[
         {
            "$match":{
               "$expr":{
                  "$in":[
                     "$_id",
                     "$$products.id"
                  ]
               }
            }
         },
         {
            "$project":{
               "_id":0,
               "id":1,
               "name":"$context.name"
            }
         }
      ],
      "as":"mergedProducts"
   }
},
{
   "$project":{
      "context":"$context",
      "mergedProducts":"$mergedProducts"
   }
},
]);

1 Ответ

2 голосов
/ 18 марта 2020

Вам нужно запустить это отображение вне $lookup, запустив $ map вместе с $ arrayElemAt , чтобы получить одну пару из обоих массивов, а затем применить $ mergeObjects чтобы получить один объект в результате:

db.Order.aggregate([
    {
        $lookup: {
            from: "products",
            localField: "context.products.id",
            foreignField: "_id",
            as: "productDetails"
        }
    },
    {
        $addFields: {
            productDetails: {
                $map: {
                    input: "$productDetails",
                    in: {
                        _id: "$$this._id",
                        name: "$$this.context.name"
                    }
                }
            }
        }
    },
    {
        $project: {
            _id: 1,
            "context.products": {
                $map: {
                    input: "$context.products",
                    as: "prod",
                    in: {
                        $mergeObjects: [
                            "$$prod",
                            { $arrayElemAt: [ { $filter: { input: "$productDetails", cond: { $eq: [ "$$this._id", "$$prod.id" ] } } }, 0 ] }
                        ]
                    }
                }
            }
        }
    }
])

Пн go Детская площадка

Целью последнего шага является создание двух массивов: products и productDetails (вывод $lookup) и найти совпадения между ними. Мы знаем, что всегда есть одно совпадение, поэтому мы можем получить только один предмет $arrayElemAt 0. В качестве результата $map будет один массив, содержащий «объединенные» документы.

...