【问题标题】:How to merge data from two collections in MongoDB如何在 MongoDB 中合并来自两个集合的数据
【发布时间】:2021-11-04 15:43:20
【问题描述】:

我目前的问题确实需要帮助。

问题:如何合并来自两个集合的数据?

第一个集合称为users,其中每个文档都包含有关一个用户的信息。此集合中 JSON 格式的文档示例:

    {
        "_id": ObjectId("userId1"),
        "nameAndSurname": "Name 1",
        "arrayOfImages": ["wwww.urlToImage1.jpeg"],
        "favouritePlayer" : "Monfils",
        "sport" : "Tennis",
        "isProfileBlocked" : false
    }

第二个集合称为user_relations,其中每个文档都包含users 集合中某个用户拥有的朋友的信息。此集合中 JSON 格式的文档示例:

    {
        "_id": ObjectId("someRandomString"),
        "userId": "userId1",
        "friendsArray": [
        {
            "userId" : "userId2",
            "lastTimestamp": 19236752642,
            "message": "Hellooo"
        },
        {
            "userId" : "userId3",
            "lastTimestamp": 12236752342,
            "message": "Yeah",
        },
        ]
    }

我有一个如下所示的 Python 查询:

db.user_relations.aggregate([
  {
    "$match": {
      "userId": "userId1"
    }
  },
  {
    "$unwind": {
      "path": "$friendsArray"
    }
  },
  {
    "$sort": {
      "friendsArray.lastTimestamp": 1
    }
  },
  {
    "$limit": 10
  },
  {
    "$replaceRoot": {
      "newRoot": "$friendsArray"
    }
  }
])

我运行该查询时的响应如下所示:

[{'userId': 'userId2', 'lastTimetamp': 19236752642, 'message': 'Yeah'}, {'userId': 'userId3', 'lastTimestamp': 12236752342, 'message': 'Hellooo'}]

现在我要做的是修改此查询,以便我可以从users 集合中为每个值(即friendsArray 中的用户)获取nameAndSurnamearrayOfImages[0] 值,以便响应可以是:

[{'userId': 'userId2', 'nameAndSurname : 'Name 2', 'pictureUrl' : 'wwww.urlToImage2.jpeg', 'lastTimestamp': 19236752642, 'message': 'Yeah'}, {'userId': 'userId3', 'nameAndSurname : 'Name 3', 'pictureUrl' : 'wwww.urlToImage3.jpeg', 'lastTimestamp': 12236752342, 'message': 'Hellooo'}]

感谢您的宝贵时间!

【问题讨论】:

    标签: mongodb mongodb-query pymongo


    【解决方案1】:

    Test code here

    您想要一个$lookup,但您想要的是类似于 SQL 的连接,根文档中的所有字段,因此添加展开和替换根以合并到 1 个文档中。

    查询

    db.user_relations.aggregate([
      {
        "$match": {
          "$expr": {
            "$eq": [
              "$userId",
              "userId1"
            ]
          }
        }
      },
      {
        "$unwind": {
          "path": "$friendsArray"
        }
      },
      {
        "$sort": {
          "friendsArray.lastTimeStamp": 1
        }
      },
      {
        "$limit": 10
      },
      {
        "$replaceRoot": {
          "newRoot": "$friendsArray"
        }
      },
      {
        "$lookup": {
          "from": "users",
          "localField": "userId",
          "foreignField": "_id",
          "as": "joined__"
        }
      },
      {
        "$unwind": {
          "path": "$joined__"
        }
      },
      {
        "$replaceRoot": {
          "newRoot": {
            "$mergeObjects": [
              "$joined__",
              "$$ROOT"
            ]
          }
        }
      },
      {
        "$project": {
          "joined__": 0
        }
      }
    ])
    

    【讨论】:

    • 非常感谢@Takis 抽出宝贵时间回答我的问题。你是我真正的救星,因为我真的需要将一些数据传输到 MongoDB。我已经更新了问题,您现在可以看到 users 集合中有一个 isProfileBlocked 字段。有什么方法可以指定该字段需要为 false,以及如何排除某些字段,例如 favouritePlayer 和 sport。我尝试过使用 $project 但它不起作用。
    • 请参阅this 添加一个过滤器并删除这两个字段,如果我们使用管道查找,我们可以过滤这些字段并在查找时删除这些字段,但性能差异很小,所以我想你对更简单的查询很好。
    • 是的,正是我想要的。谢谢你的帮助! :)
    • 嘿@Takis,我遇到了一个小问题。我的 _id 字段不是字符串,而是 ObjectId。当我尝试运行此查询时,它给了我错误。我在互联网上进行了研究,但找不到令人满意的答案。你知道我该如何解决它。感谢您的帮助!
    • 我不知道可能是什么问题,但是如果类型是问题,我们有两个函数$toObjectId$toString 允许我们进行转换。制作例如 "61448da8c1a2f7417cea0977" <-> ObjectId("61448da8c1a2f7417cea0977") 。我使用字符串是因为ObjectId("userId1") 会导致错误,ObjectId 仅将 1 个长度为 24 的十六进制字符串作为参数。如果您想使用自定义 _ids 可能使用简单的数字?或使用驱动程序为您生成 ObjectId。
    猜你喜欢
    • 2013-04-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-22
    • 1970-01-01
    • 1970-01-01
    • 2011-08-06
    相关资源
    最近更新 更多