在 MongoDB 中查找共享键值的两个文档

2023-11-24

我在 MongoDB 中有大量文档,每个文档都有一个名为“name”的键,另一个名为“type”的键。我想找到两个文件一样的名字 and 不同种类,一个简单的 MongoDB 对应项

SELECT ...
FROM table AS t1, table AS t2
WHERE t1.name = t2.name AND t1.type <> t2.type

我可以想象,可以使用聚合来做到这一点:但是,该集合非常大,处理它需要时间,而且我正在寻找一对这样的文档。


虽然我坚持认为您提出问题的方式实际上与您遇到的特定问题无关,但我会以某种方式解释 MongoDB 类型的解决方案中惯用的 SQL 方式。我认为你的实际解决方案会有所不同,但你没有向我们提出这个问题,而只是向我们提出了 SQL。

因此,请考虑以下文档作为示例集,为了清楚起见,删除此列表中的 _id 字段:

{ "name" : "a", "type" : "b" }
{ "name" : "a", "type" : "c" }
{ "name" : "b", "type" : "c" }
{ "name" : "b", "type" : "a" }
{ "name" : "a", "type" : "b" }
{ "name" : "b", "type" : "c" }
{ "name" : "f", "type" : "e" }
{ "name" : "z", "type" : "z" }
{ "name" : "z", "type" : "z" }

如果我们对相同的数据运行 SQL,我们将得到以下结果:

a|b
a|c
a|c
b|c
b|a
b|a
a|b
b|c

我们可以看到2个文档不匹配,然后推导出SQL操作的逻辑。所以另一种说法是“哪些文档给出了“名称”键do有超过one键“type”中的可能值。

鉴于此,采用 mongo 方法,我们可以查询以下项目do not符合给定的条件。所以有效地reverse结果:

db.sample.aggregate([

    // Store unique documents grouped by the "name"
    {$group: { 
        _id: "$name",
        comp: {
            $addToSet: { 
                name:"$name",
                type: "$type" 
            }
        } 
    }},

    // Unwind the "set" results
    {$unwind: "$comp"},

    // Push the results back to get the unique count
    // *note* you could not have done this with alongside $addtoSet
    {$group: {
        _id: "$_id",
        comp: {
            $push: { 
                name: "$comp.name",
                type: "$comp.type" 
            }
        },
        count: {$sum: 1} 
    }},

    // Match only what was counted once
    {$match: {count: 1}},

    // Unwind the array
    {$unwind: "$comp"},

    // Clean up to "name" and "type" only
    {$project: { _id: 0, name: "$comp.name", type: "$comp.type"}}

])

此操作将产生结果:

{ "name" : "f", "type" : "e" }
{ "name" : "z", "type" : "z" }

现在,为了获得与 SQL 查询相同的结果,我们将获取这些结果并将它们引导到另一个查询中:

db.sample.find({$nor: [{ name: "f", type: "e"},{ name: "z", type: "z"}] })

最终匹配结果为:

{ "name" : "a", "type" : "b" }
{ "name" : "a", "type" : "c" }
{ "name" : "b", "type" : "c" }
{ "name" : "b", "type" : "a" }
{ "name" : "a", "type" : "b" }
{ "name" : "b", "type" : "c" }

所以这会起作用,但是可能使这不切实际的一件事是文档的数量compared非常大,我们在将这些结果压缩为数组时遇到了工作限制。

它也因使用而受到一些影响negative在最终的查找操作中,这将强制扫描集合。但平心而论,使用相同的 SQL 查询也可以这样说negative前提。

Edit

当然我没有提到的是,如果结果集相反并且你正在匹配more结果是从聚合中排除的项目,然后只需反转逻辑即可获取所需的键。只需更改 $match 如下:

{$match: {$gt: 1}}

这就是结果,也许不是实际的文件,但它是一个结果。因此,您不需要另一个查询来匹配否定案例。

而且,归根结底,这是我的错,因为我太专注于惯用翻译,而没有做到这一点。read你问题的最后一行,去哪里do说你正在寻找one文档。

当然,现在如果结果大小大于 16MB,那么您就会陷入困境。至少直到2.6发布,其中聚合操作的结果是cursor,所以你可以像这样迭代.find().

还介绍了2.6 is the $size运算符用于查找文档中数组的大小。所以这将有助于删除第二个$unwind and $group用于获取集合的长度。这会将查询更改为更快的形式:

db.sample.aggregate([
    {$group: { 
        _id: "$name",
        comp: {
            $addToSet: { 
                name:"$name",
                type: "$type"
            }
        } 
    }},
    {$project: { 
        comp: 1,
        count: {$size: "$comp"} 
    }},
    {$match: {count: {$gt: 1}}},
    {$unwind: "$comp"},
    {$project: { _id: 0, name: "$comp.name", type: "$comp.type"}}
])

如果您只是为了个人使用或开发/测试而执行此操作,则当前可以使用 MongoDB 2.6.0-rc0。


故事的道德启示。是的,就是你can do it, But do you really想要或need这样做吗?那么可能不会,如果您针对特定业务案例提出不同的问题,您可能会得到不同的答案。但话又说回来,这可能完全适合你想要的。

Note

值得一提的是,当你查看 SQL 的结果时,它会错误地复制如果您没有使用其他可用类型选项,则有几个项目DISTINCT对于这些值或本质上是另一个分组。但这是使用 MongoDB 的过程产生的结果。

为了亚历山大

这是当前 2.4.x 版本中 shell 中聚合的输出:

{
    "result" : [
            {
                    "name" : "f",
                    "type" : "e"
            },
            {
                    "name" : "z",
                    "type" : "z"
            }
    ],
    "ok" : 1
}

因此,这样做可以让 var 作为参数传递给第二个查找中的 $nor 条件,如下所示:

var cond = db.sample.aggregate([ .....

db.sample.find({$nor: cond.result })

您应该得到相同的结果。否则请咨询您的司机。

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

在 MongoDB 中查找共享键值的两个文档 的相关文章

随机推荐

  • 在 Rmarkdown HTML 输出中禁止来自 RStan 的运行消息

    以下是我的 r 代码 r message FALSE warning FALSE cache 0 eval TRUE error FALSE stan m1 lt rethinking map2stan alist y dbinom n p
  • 如何创建紧凑型材

    我在谷歌上搜索找到一种在 Java 1 8 中创建紧凑配置文件的方法 是否可以创建紧凑配置文件 因为Here说它仅适用于嵌入式版本 简短回答 JEP 161说配置文件必须在 Java 8 中 确实如此 要创建它们 请使用make profi
  • 尝试使用 numpy 向量化迭代计算

    我试图通过使用 numpy 中的向量化形式来使某些代码更有效 让我给你举个例子 这样你就明白我的意思了 给出以下代码 a np zeros 4 4 a 0 1 2 3 4 for i in range len a 1 a i 1 2 a i
  • 通过 Rails 迁移添加数据库列并基于另一列填充它

    我正在编写一个迁移以向表中添加一列 该列的值取决于另外两个现有列的值 最好 最快的方法是什么 目前我有这个 但不确定这是否是最好的方法 因为组表可能非常大 class AddColorToGroup lt ActiveRecord Migr
  • 有效 Cookie 值的明确指南

    我知道还有其他问题 但他们的答案似乎是假设而不是确定的 我有限的理解是cookie值是 分号已用于分隔单个 cookie 中的 cookie 属性 等号用于分隔 cookie 名称和值 冒号用于分隔标头中的多个 cookie 还有其他 特殊
  • Chrome 不缓存图像/js/css

    当 Chrome 加载我的网站时 它会在显示文件之前检查服务器是否有文件的更新版本 图像 Javascript CSS 它从服务器获取 304 因为我从不编辑外部 javascript css 或图像 我想要它做的是显示图像 甚至无需检查服
  • 在 C 和 C++ 中使用浮点转换与浮点后缀有什么区别吗?

    这之间有区别吗 使用浮点文字后缀 float MY FLOAT 3 14159265358979323846264338328f f suffix double MY DOUBLE 3 141592653589793238462643383
  • Bash:无法在管道右侧构建数组

    有人知道为什么这段代码不能按预期工作吗 gt svnTags gt svn ls http plugins svn wordpress org duplicate post tags while read line do slashless
  • 实体框架 4 实体状态未更改触发更新

    我正在使用 EF 4 使用存储过程映射我的实体的所有 CUD 操作 我有两个表 地址和人员 一个人可以有多个与其关联的地址 这是我正在运行的代码 Person person from p in context People where p
  • JavaScriptSerializer - 枚举作为字符串的 JSON 序列化

    我有一堂课 其中包含enum属性 并在使用序列化对象时JavaScriptSerializer 我的 json 结果包含枚举的整数值而不是它的string 姓名 有没有办法让枚举作为string在我的 json 中 无需创建自定义JavaS
  • 当您等待失败的任务时会发生什么

    我有一个理论问题要问你 如果我在另一个任务中等待一个任务的结果 会发生什么 我想知道我现在的系统以后是否还能工作 任务启动并执行一些操作 在某些时候 该任务可能需要另一个任务来处理当前任务本身无法处理的数据 所以我使用await来确保只要他
  • Codeigniter php7 错误

    我在 Codeigniter 2 上有一个网站 当我将服务器版本切换到 PHP7 时 出现以下两个错误 遇到 PHP 错误严重性 通知 消息 仅应通过引用分配变量 文件名 core Controller php 线路编号 51 this g
  • 在 Android 中拨打 911

    我想使用 Android SDK 拨打紧急号码 我正在使用以下代码拨打号码 911 此代码适用于除 911 紧急号码 之外的所有号码 当我使用 911 时 它会显示我不想要的拨号屏幕 是否有任何程序可以在不打开拨号器的情况下拨打 911 或
  • 以编程方式将 Power BI 报表部署到 Power BI 报表服务器并更改连接字符串

    是否有任何方法可以将 Power BI 报表部署到 Power BI 报表服务器 而无需手动复制这些文件 将它们上传到服务器 最后逐个报表地更改每个报表的数据源连接信息 这在每个报表中都不实用客户站点 例如 PowerBI 报告文件 Rep
  • bmake 的优点

    除了 bmake 是 GNU make 的 BSD 等价物这一事实之外 我无法清楚地理解它相对于 GNU make 的优势 谁能帮我 我只能找到一个resource这有点帮助 感谢更多帮助或指示 BSD make 和 GNU make 都是
  • 如何获取一周以上的推文(使用 tweepy 或其他 python 库)

    我一直在试图解决这个问题 但这确实令人沮丧 我正在尝试使用 Tweepy 获取带有特定主题标签的推文 大量推文 但这不会追溯到超过一周 我需要回到至少两年前 持续几个月 这可能吗 如果可能的话 怎么办 只是为了检查这里是我的代码 impor
  • mysql 游标中的记录数而不迭代?

    我正在尝试为以下逻辑编写 mysql 程序 select id fullname from users where fullname like concat lastname firstname middlename 如果上面的查询返回 0
  • Pandas json_normalize 产生令人困惑的“KeyError”消息?

    我正在尝试将嵌套 JSON 转换为 Pandas 数据帧 我一直在使用json normalize一直成功 直到我遇到了某个 JSON 我制作了一个较小的版本来重现问题 from pandas io json import json nor
  • 为什么某些 IDE 不缩进 switch 内的 case 语句? [复制]

    这个问题在这里已经有答案了 可能的重复 为什么人们不缩进 C 访问说明符 case 语句 我有一个语法问题 不是关于how 而是why 许多 IDE 例如 Eclipse 和 Qt Creator 会自动缩进switch像这样 Day ra
  • 在 MongoDB 中查找共享键值的两个文档

    我在 MongoDB 中有大量文档 每个文档都有一个名为 name 的键 另一个名为 type 的键 我想找到两个文件一样的名字 and 不同种类 一个简单的 MongoDB 对应项 SELECT FROM table AS t1 tabl