将 $lookup 结果合并到现有数组

2024-05-05

我是 mongo 新手,我需要你的帮助。

我有收藏学习计划。这是示例文档:

{
    "_id" : "dGFY",
    "garranti" : [
        {
            "typ" : {
                "sk" : "garant",
                "en" : "Chairman of study board"
            },
            "id" : "1025769"
        },
        {
            "typ" : {
                "sk" : "predseda odborovej komisie",
                "en" : "Chairman of study board"
            },
            "id" : "1025769"
        }
    ]
}

接下来我有收藏osoby.
示例文档:

{
    "_id" : "1025769",
    "plneMeno" : "prof. RNDr. Peter Moczo, DrSc.",
    "priezvisko" : "Moczo",
    "meno" : "Peter",
    "jeGarantProgramu" : "dGFY/x"
}

我需要的是添加文档osoby到数组中对应的文档garranti(其中studijneProgramy.garanti.id == osoby._id)。 所以这是我想要的结果:

{
    "_id" : "dGFY",
    "garranti" : [
        {
            "typ" : {
                "sk" : "garant",
                "en" : "Chairman of study board"
            },
            "id" : "1025769"
            "garant":{
                "_id" : "1025769",
                "plneMeno" : "prof. RNDr. Peter Moczo, DrSc.",
                "priezvisko" : "Moczo",
                "meno" : "Peter",
                "jeGarantProgramu" : "dGFY/x"
            }
        },
        {
            "typ" : {
                "sk" : "predseda odborovej komisie",
                "en" : "Chairman of study board"
            },
            "id" : "1025769"
            "garant":{
                "_id" : "1025769",
                "plneMeno" : "prof. RNDr. Peter Moczo, DrSc.",
                "priezvisko" : "Moczo",
                "meno" : "Peter",
                "jeGarantProgramu" : "dGFY/x"
            }
        }
    ]
}

我尝试了这个聚合,但它替换了内容garranti.

db.studijneProgramy.aggregate([
{
    $lookup:
    {
        from:"osoby", 
        localField:"garranti.id",
        foreignField:"_id", 
        as:"garranti.garant"
    }
 }
]
).pretty()

任何帮助将不胜感激!


MongoDB $lookup https://docs.mongodb.com/manual/reference/operator/aggregation/lookup/不会使用“查找”集合中的匹配项“更新”现有数组中的元素。它会only输出与给定条件匹配的“数组”,与您拥有的值的“现有数组”或奇异值相匹配。

为了将条目与“服务器”“结婚”$lookup https://docs.mongodb.com/manual/reference/operator/aggregation/lookup/操作,您必须继续执行以下选项之一才能以您想要的形式返回。

$首先展开数组

最简单的形式是简单地更改文档的结构,以便源中的每个数组成员都是它的首先自己的文档,在您真正尝试“结合”相关信息之前:

db.studijneProgramy.aggregate([
  { "$unwind": "$garranti" },
  { "$lookup": {
    "from": "osoby",
    "as": "garranti.garrant",
    "localField": "garranti.id",
    "foreignField": "_id"
  }},
  { "$unwind": "$garranti.garrant" },
  { "$group": {
    "_id": "$_id",
    "garranti": { "$push": "$garranti" }
  }}
])

由于原始数组材料现在是单个文档,因此每个文档仅接收来自连接集合的匹配“数组”。这个会$unwind https://docs.mongodb.com/manual/reference/operator/aggregation/unwind/再次使用$group https://docs.mongodb.com/manual/reference/operator/aggregation/group/为了$push https://docs.mongodb.com/manual/reference/operator/aggregation/push/到带有“连接”条目的最终数组形式。

关联“数组”

在支持它的版本中有点花哨的是使用以下功能$indexOfArray https://docs.mongodb.com/manual/reference/operator/aggregation/indexOfArray/ and $arrayElemAt https://docs.mongodb.com/manual/reference/operator/aggregation/indexOfArray/为了“匹配”输出数组$lookup https://docs.mongodb.com/manual/reference/operator/aggregation/lookup/到文档中现有的数组条目:

db.studijneProgramy.aggregate([
  { "$lookup": {
    "from": "osoby",
    "as": "related",
    "localField": "garranti.id",
    "foreignField": "_id"
  }},
  { "$project": {
    "garranti": {
      "$map": {
        "input": "$garranti",
        "in": {
          "typ": "$$this.typ",
          "id": "$$this.id",
          "garrant": {
            "$arrayElemAt": [
              "$related",
              { "$indexOfArray": [ "$related._id", "$$this.id" ] }
            ]
          }
        }
      }
    }
  }}
])

因此查找返回“匹配数组”(related)然后您“查找”这些匹配的条目并将它们转置到原始文档数组中$map https://docs.mongodb.com/manual/reference/operator/aggregation/map/。当然这需要额外的$project https://docs.mongodb.com/manual/reference/operator/aggregation/project/stage 或类似的内容,以便重塑文档结果,因为您无法“定位”现有数组的每个元素$lookup https://docs.mongodb.com/manual/reference/operator/aggregation/lookup/输出如前所述。

这实际上是“服务器”上某些库(例如“mongoose”)为“客户端上的连接模拟”所做的直接关联。实际上,“外部”条目被“映射”到现有数组上。

子管道处理

有点花哨和冗长的是使用“子管道”处理的另一种选择不相关子查询 https://docs.mongodb.com/manual/reference/operator/aggregation/lookup/#uncorrelated-subquery从 MongoDB 3.6 及以上版本可用。这里我们基本上是在“子管道”中进行操作$lookup https://docs.mongodb.com/manual/reference/operator/aggregation/lookup/而不是在后续聚合阶段进行处理:

db.studijneProgramy.aggregate([
  { "$lookup": {
    "from": "osoby",
    "as": "garranti",
    "let": { "garranti": "$garranti" },
    "pipeline": [
      { "$match": {
        "$expr": { "$in": [ "$_id", "$$garranti.id" ] } 
      }},
      { "$addFields": {
        "docs": {
          "$filter": {
            "input": "$$garranti",
            "cond": {
              "$eq": [ "$$this.id", "$_id" ]
            }
          }
        }
      }},
      { "$unwind": "$docs" },
      { "$replaceRoot": {
        "newRoot": {
          "$mergeObjects": [
            "$docs",
            { "garrant": {
              "$arrayToObject": {
                "$filter": { 
                  "input": { "$objectToArray": "$$ROOT" },
                  "cond": { "$ne": [ "$$this.k", "docs"] }
                }
              }
            }}
          ]
        }
      }}
    ]
  }}
])

这种方式将操作“彻底”转变,并有效地将“源文档”中的“匹配数组元素”作为数组放入每个匹配的外部元素中。

然后处理有效地使用$unwind https://docs.mongodb.com/manual/reference/operator/aggregation/lookup/在过滤后的源列表上,然后合并外部集合中的内容,因此现在看来$lookup https://docs.mongodb.com/manual/reference/operator/aggregation/lookup/“输出数组”实际上是来自“本地数组”的数据,现在与“外部内容”“合并”。

实际上,这只是对相同内容的更奇特的调用$map https://docs.mongodb.com/manual/reference/operator/aggregation/map/上面的过程,但是对条目进行“关联”before结果与原始父文档合并,覆盖原始数组属性。


我认为某个地方有一个 JIRA 可以解决这个问题,但我有一种感觉“按设计工作”所有此类报告均已标记,因此不太可能改变目前的做法。

因此,您的误解是“连接”会“自动”与数组条目“合并”。它不是。

如果您实际上想“合并数组输出”,那么上面的方法就是“服务器”方法。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将 $lookup 结果合并到现有数组 的相关文章

  • 如何使用 node.js / mongodb 在 HTML 中显示任意、无模式数据

    我使用 mongodb 将应用程序错误日志存储为 json 文档 我希望能够将错误日志格式化为 HTML 而不是将纯 json 返回到浏览器 日志是完全无模式的 它们可以随时更改 因此尝试执行此操作 在 Jade 中 是没有用的 var i
  • Mongoose 限制/偏移量和计数查询

    查询性能有点奇怪 我需要运行一个查询来计算文档总数 并且还可以返回一个可以限制和偏移的结果集 所以 我总共有 57 个文档 用户想要 10 个文档偏移 20 我可以想到两种方法来做到这一点 首先是查询所有 57 个文档 以数组形式返回 然后
  • 我如何在 mongodb 的数组中找到文本搜索

    id objectId 23651478 name Tomatos array title Vegetables description Vegitables are good to health id objectId 45761244
  • 如何使用 Sails.js 和 Waterline 更新 MongoDB 子文档中的特定键?

    当尝试使用 Sails js 和 Waterline ORM 更新 MongoDB 子文档中的单个键时 我遇到了问题 这就是我的person js模型看起来像 module exports attributes name type stri
  • 猫鼬的深层填充

    我有两个模式 一张用于用户 另一张用于帖子 在用户模式中 我有latestPost的一个属性 它是帖子模式中条目的ObjectId 当我加载用户对象时 我想将 lastestPost 作为对象获取 其中包含用户架构中作者的用户名 其中作者是
  • 如何在 Mongoose 中执行查找查询?

    我在 mongodb 中有一组电子书数据 例如 id ObjectId 58b56fe19585b10cd42981d8 cover path D Ebooks uploads ebooks cover 1488285665748 img1
  • MongoDB 在仅返回 _id 时使用 COLLSCAN

    我想返回 MongoDB 集合中的所有 ID 我使用了以下代码 db coll find id 1 但MongoDB扫描整个集合而不是从默认读取信息index id 1 从日志中 find collection filter project
  • Mongoid 命名范围比较同一文档中的两个时间字段

    我需要在 Mongoid 中创建一个命名范围来比较同一文档中的两个时间字段 例如 scope foo where gt updated at gt gt checked at 这显然不会像它对待的那样起作用 checked at作为一个符号
  • 在 MongoDb 上序列化仅获取属性

    使用 C 6 我可以写 public class Person public Guid Id get public string Name get public Person Guid id string name Id id Name n
  • Node.js 重用 MongoDB 参考

    我无法理解 Node js 例如 MongoDB 访问 这是我得到的 mydb js var mongodb require mongodb server new mongodb Server staff mongohq com 10030
  • 元素数组中数组的 MongoDB 全文

    当元素数组中的数组包含应与我的搜索匹配的文本时 我无法检索文档 以下是两个示例文档 id foo name Thing1 data text X X name Thing2 data text X Y id foo
  • MONGODB [DEBUG] 游标的cursor.refresh() 7078636577051629992

    更新大型 json 列表时 出现以下错误 2012 04 01T09 34 00 00 00 app run 1 MONGODB DEBUG cursor refresh for cursor 7078636577051629992 201
  • 让 MongoDB 在 Linux 上监听远程连接

    我已在 Windows 本地计算机上 上成功安装 MongoDB 作为服务 但现在我想将 MongoDb 移动到单独的服务器 所以我将 tarball 解压到网络上的虚拟服务器 运行 Linux 当我从本地计算机使用 PuTTY 连接到服务
  • 修复数据库需要多少额外空间

    我已经问过了这个问题在 mongodb google group https groups google com d topic mongodb user oi6S LKfTrs discussion 在没有任何回复的情况下将其发布在这里
  • 在 mongodb 和 nodejs 中对博客和评级进行建模

    我有一个博客集合 其中包含用户给予的标题 正文和综合评分 另一个集合 评级 其架构引用了博客 以对象 ID 的形式对博客进行评级 如果有的话 的用户以及他们给出的评级 即 1 或 1 当特定用户按照 最新优先 的顺序浏览博客时 比如每页 4
  • 无法对 mongo 进行身份验证,“身份验证失败”

    我使用以下说明为 mongo 创建了一个管理员用户 http docs mongodb org manual tutorial add user administrator http docs mongodb org manual tuto
  • MongoDB中如何通过引用字段进行查询?

    我有两个 Mongo 模式 User id ObjectId name String country ObjectId Reference to schema Country Country id ObjectId name String
  • 最小验证在 Mongoose 中不起作用

    我有一个架构 其中余额字段的声明如下所示 balance type Number min 0 default 30 我将 0 设置为最小值 这样余额就不会为负值 但是当我通过更新查询减少余额值时 余额结果是负值 我的更新查询 User up
  • Mongodb:语法错误:意外的标识符

    我是 mongodb 的新手 我正在使用 mongolab 创建免费数据库 我的数据库名称是 enron 使用在线 mongoshell 连接到 mongo 数据库然后发生错误 mongo ds033499 mongolab com 334
  • 减少从 MongoDB 加载大熊猫数据帧所使用的内存

    我有一个大型数据集 包含 4000 万条记录 总大小约为 21 0G 存储在 MongoDB 中 我花了几个小时将其加载到 pandas 数据框中 但总内存大小增加到约 28 7G 加载之前约为 600Mb cursor mongocoll

随机推荐