MongoDB $查找对象数组

MongoDB $lookup on array of objects

类别

    {
        "_id" : ObjectId("61740086893f048528d166b9"),
        "name": "Category1",
        "tracks" : [ 
            "61c65353565a2d9a1cd3020d", 
            "61c74518962dc3efb96c3438", 
            "61c74775703176a6f72df444"
        ]
    }

曲目

    {
        "_id" : ObjectId("61c65353565a2d9a1cd3020d"),
        "name" : "Track1",
        "categoryId" : ObjectId("61740086893f048528d166b9"),
        "creatorId" : ObjectId("61c6478304e98ed63e8ee7d3"),
        "thumbnailId" : ObjectId("61c65353565a2d9a1cd3020c"),
        "plays" : [],
        "media" : {
            "type" : "wav",
            "url" : ""
        },
        "status" : "approved",
        "downloads" : [],
        "uploadedDate" : 1640387411
    }

假设我有 5 个类别,每个类别都有很多曲目 ID,我想为每个类别获取 N 个最后的曲目,所以我使用了下面的代码

    categories.aggregate([
        {
            $project: {
                tracks: { $slice: ["$tracks", -2] },
            },
        },
    ]

响应是

    [
        {
            "_id": "61740086893f048528d166b9",
            "tracks": [
                "61c74518962dc3efb96c3438",
                "61c74775703176a6f72df444"
            ]
        },
        {
            "_id": "61740094893f048528d166c1",
            "tracks": []
        },
        {
            "_id": "617400a0893f048528d166cb",
            "tracks": []
        }
    ]

到目前为止还不错,但问题是如何将每个类别的曲目从 ID 数组替换为对象数组?

我尝试了 $loopup,但我可能没有正确实施 localField

预期结果

    [
        {
            "_id": "61740086893f048528d166b9",
            "tracks": [
                {
                    "_id": ObjectId("61c74518962dc3efb96c3438")
                    ...
                },
                {
                    "_id": ObjectId("61c74775703176a6f72df444")
                    ...
                }
            ]
        },
        {
            "_id": "61740094893f048528d166c1",
            "tracks": []
        },
        {
            "_id": "617400a0893f048528d166cb",
            "tracks": []
        }
    ]

***** 更新 *****

我正在尝试用 createdBy 替换 creatorId,这是 users 集合

中用户的一个对象

用户

    {
      "_id": ObjectId("61c6478304e98ed63e8ee7cb"),
      "email": "USER888@gmail.com",
      "username": "USER999",
      "tracks": [
        ObjectId("61c65353565a2d9a1cd3020d"),
      ],
    }

预期的结果应该是

    [
        {
            "_id": "61740086893f048528d166b9",
            "tracks": [
                {
                    "_id": ObjectId("61c74518962dc3efb96c3438"),
                    "createdBy": {
                        "_id": "userId"
                        ...
                    },
                    ...
                },
                {
                    "_id": ObjectId("61c74775703176a6f72df444"),
                    "createdBy": {
                        "_id": "userId"
                        ...
                    }
                    ...
                }
            ]
        },
        {
            "_id": "61740094893f048528d166c1",
            "tracks": []
        },
        {
            "_id": "617400a0893f048528d166cb",
            "tracks": []
        }
    ]

除了ray下面的解决方案外,我在此处添加了代码https://mongoplayground.net/p/8AjmnL-vhtz

createdBy在最顶层,但不是在每个轨道下

$lookup 是您在 Tracks 集合中找到相应对象的正确方法。为什么您的代码不起作用是因为您将字符串存储在 Categories 集合中的 tracks 数组中;而 Tracks 集合的 _id 是 ObjectId。由于数据类型不匹配,因此不会有 $lookup 结果。您可以做的是通过在 $map 中使用 $toObjectId 将字符串转换为 ObjectId,然后执行 $lookup

db.categories.aggregate([
  {
    $project: {
      tracks: {
        $slice: [
          "$tracks",
          -2
        ]
      }
    }
  },
  {
    $project: {
      tracks: {
        "$map": {
          "input": "$tracks",
          "as": "t",
          "in": {
            "$toObjectId": "$$t"
          }
        }
      }
    }
  },
  {
    "$lookup": {
      "from": "tracks",
      let: {
        t: "$tracks"
      },
      pipeline: [
        {
          $match: {
            $expr: {
              "$in": [
                "$_id",
                "$$t"
              ]
            }
          }
        }
      ],
      "as": "tracks"
    }
  }
])

这里是Mongo playground供您参考。