【问题标题】:MongoDB $lookup and $map array of objectsMongoDB $lookup 和 $map 对象数组
【发布时间】:2021-03-10 20:18:45
【问题描述】:

我尝试了几天,但找不到任何成功

我正在使用 MongoDB,我尝试使用许多管道步骤来完成它,但我找不到方法。

我有一个玩家集合,每个玩家包含一个items 数组

{
    "_id": ObjectId("5fba17c1c4566e57fafdcd7e"),
    "username": "moshe",
    "items": [
        {
            "_id": ObjectId("5fbb5ac178045a985690b5fd"),
            "equipped": false,
            "itemId": "5fbb5ab778045a985690b5fc"
        }
    ]
}

我有一个项目集合,其中包含有关每个项目的更多信息 在播放器items 数组中。

{
    "_id": ObjectId("5fbb5ab778045a985690b5fc"),
    "name": "Axe",
    "damage": 4,
    "defense": 6
}

我的目标是在他的items 数组中创建一个包含有关该项目的所有信息的播放器文档,所以它看起来像这样:

{
    "_id": ObjectId("5fba17c1c4566e57fafdcd7e"),
    "username": "moshe",
    "items": [
        {
            "_id": ObjectId("5fbb5ac178045a985690b5fd"),
            "equipped": false,
            "itemId": "5fbb5ab778045a985690b5fc",
            "name": "Axe",
            "damage": 4,
            "defense": 6
        }
    ]
}

【问题讨论】:

    标签: mongodb mongodb-query aggregation


    【解决方案1】:
    • $unwind解构items数组
    • $lookup 加入 items 集合,在使用 $toObjectId 将其转换为对象 ID 后将 itemsId 传递给 let 并传递 items 对象,
      • $matchitemId条件
      • $mergeObject 合并 items 对象和 $$ROOT 对象并使用 $replaceRoot 替换为根
    • $group 再次重构items 数组,按_id 分组并获得第一个username 并构造items 数组
    db.players.aggregate([
      { $unwind: "$items" },
      {
        $lookup: {
          from: "items",
          let: {
            itemId: { $toObjectId: "$items.itemId" },
            items: "$items"
          },
          pipeline: [
            { $match: { $expr: { $eq: ["$_id", "$$itemId" ] } } },
            { $replaceRoot: { newRoot: { $mergeObjects: ["$$items", "$$ROOT"] } } }
          ],
          as: "items"
        }
      },
      {
        $group: {
          _id: "$_id",
          username: { $first: "$username" },
          items: { $push: { $first: "$items" } }
        }
      }
    ])
    

    Playground


    第二个选项使用$map,不使用$unwind

    • $addFields for items 使用 $toObjectId$mapitemId 字符串转换为对象类型 id
    • $lookup加入items收藏
    • $project 显示必填字段,并合并 items 数组和 itemsCollection 使用 $map 迭代项目数组 $filter 的循环以获得匹配的 itemId$first 从返回结果中获取第一个对象,@ 987654358@ 合并当前对象和从$first 返回的对象
    db.players.aggregate([
      {
        $addFields: {
          items: {
            $map: {
              input: "$items",
              in: {
                $mergeObjects: ["$$this", { itemId: { $toObjectId: "$$this.itemId" } }]
              }
            }
          }
        }
      },
      {
        $lookup: {
          from: "items",
          localField: "items.itemId",
          foreignField: "_id",
          as: "itemsCollection"
        }
      },
      {
        $project: {
          username: 1,
          items: {
            $map: {
              input: "$items",
              as: "i",
              in: {
                $mergeObjects: [
                  "$$i",
                  {
                    $first: {
                      $filter: {
                        input: "$itemsCollection",
                        cond: { $eq: ["$$this._id", "$$i.itemId"] }
                      }
                    }
                  }
                ]
              }
            }
          }
        }
      }
    ])
    

    Playground

    【讨论】:

      【解决方案2】:

      首先我强烈建议您将items.itemId 存储为ObjectId,而不是字符串。

      那么另一个简单的解决方案可以是:

      db.players.aggregate([
        {
          $lookup: {
            from: "items",
            localField: "items.itemId",
            foreignField: "_id",
            as: "itemsDocuments",
          },
        },
        {
          $addFields: {
            items: {
              $map: {
                input: { $zip: { inputs: ["$items", "$itemsDocuments"] } },
                in: { $mergeObjects: "$$this" },
              },
            },
          },
        },
        { $unset: "itemsDocuments" },
      ])
      

      【讨论】:

        猜你喜欢
        • 2021-04-20
        • 2020-11-12
        • 2020-08-18
        • 2018-11-30
        • 1970-01-01
        • 2021-11-16
        • 2021-06-10
        • 2018-07-26
        相关资源
        最近更新 更多