MongoDB Aggregate $ lookup для массива объекта с дополнительным полем - PullRequest
1 голос
/ 30 апреля 2020

У меня есть две разные коллекции (пример ниже) методы & items . На данный момент я использую предварительный запрос агрегирования 3.6 для $lookup:

MongoPlayground Пример

  {
    $lookup: {
      from: "items",
      localField: "reagents._id",
      foreignField: "_id",
      as: "reagent_items"
    }
  }

Проблема в том, что если я использую его Я скучаю по полю quantity (из methods.reagents врезано) на этапе $lookup из оригинальной коллекции. Сейчас я возвращаю quantity сразу после lookup, но, как я слышал, Mon go ввел из 3.6 новый синтаксис для lookup запросов, поэтому вопрос:

Можно ли решить мою проблему для получения следующих результатов:

  {
    "_id": 1,
    "name": "Test",
    "reagent_items": [ // <= the exact schema of what I need after lookup
      {
        "_id": 1,
        "name": "ItemOne",
        "other": "field",
        "quantity": 2 //quantity field from original {array of objects} after lookup
      },
      {
        "_id": 2,
        "name": "ItemTwo",
        "other": "field",
        "quantity": 4 //quantity field from original {array of objects} after lookup
      }
    ],
    "reagents": [ //original reagents field here just for example, we could remove it
      {
        "_id": 1,
        "quantity": 2
      },
      {
        "_id": 2,
        "quantity": 4
      }
    ]
  }

методы

    {
      "_id": 1,
      "name": "Test",
      "reagents": [
        {
          _id: 1,
          quantity: 2
        },
        {
          _id: 2,
          quantity: 4
        }
      ]
    }

элементы

    {
      "_id": 1,
      "name": "ItemOne",
      "other": "field"
    },
    {
      "_id": 2,
      "name": "ItemTwo",
      "other": "field"
    }

1 Ответ

2 голосов
/ 30 апреля 2020

Используйте $ map вместе с $ arrayElemAt , чтобы найти соответствующие reagent для каждого reagent_items и примените $ mergeObjects , чтобы получить один объект:

db.methods.aggregate([
    {
        $lookup: {
            from: "items",
            localField: "reagents._id",
            foreignField: "_id",
            as: "reagent_items"
        }
    },
    {
        $project: {
            _id:1,
            name: 1,
            reagents: 1,
            reagent_items: {
                $map: {
                    input: "$reagent_items",
                    as: "ri",
                    in: {
                        $mergeObjects: [
                            "$$ri",
                            {
                                $arrayElemAt: [ { $filter: { input: "$reagents", cond: { $eq: [ "$$this._id", "$$ri._id" ] } } }, 0 ]
                            }
                        ]
                    }
                }
            }
        }
    }
])

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

...