在 MongoDB 中使用 MapReduce 连接两个集合

2024-01-21

我已经知道 MongoDB 不支持连接操作,但我必须模拟一个$lookup(来自聚合框架)mapReduce范例。

我的两个收藏是:

// Employees sample 
{
  "_id" : "1234",
  "first_name" : "John",
  "last_name" : "Bush",
  "departments" : 
  [ 
    { "dep_id" : "d001", "hire_date" : "date001" },
    { "dep_id" : "d004", "hire_date" : "date004" }
  ]
}
{ 
  "_id" : "5678", 
  "first_name" : "Johny", 
  "last_name" : "Cash", 
  "departments" : [ { "dep_id" : "d001", "hire_date" : "date03" } ] 
}
{ 
  "_id" : "9012", 
  "first_name" : "Susan", 
  "last_name" : "Bowdy", 
  "departments" : [ { "dep_id" : "d004", "hire_date" : "date04" } ] 
}

// Departments sample 
{
  "_id" : "d001",
  "dep_name" : "Sales",
  "employees" : [ "1234", "5678" ]
},
{
  "_id" : "d004",
  "name" : "Quality M",
  "employees" : [ "1234", "9012" ]
}

实际上我希望得到这样的结果:

{
  "_id" : "1234",
  "value" : 
  {
    "first_name" : "John",
    "departments" :
    [
      { "dep_id" : "d001", "dep_name" : "Sales" },
      { "dep_id" : "d004", "dep_name" : "Quality M" }
    ]
  }
}
{ 
  "_id" : "5678", 
  "value" : 
  { 
    "first_name" : "Johnny", 
    "departments" : [ { "dep_id" : "d001", "dep_name" : "Sales" } ]
  } 
}
{ 
  "_id" : "9012", 
  "value" : 
  { 
    "first_name" : "Susan", 
    "departments" : [ { "dep_id" : "d004", "dep_name" : "Quality M" } ] 
  } 
}

常见的字段有dep_id(来自员工)和_id(来自部门)。

我的代码是下一个,但它不能按我的需要工作。

var mapD = function() {
  for (var i=0; i<this.employees.length; i++) {
    emit(this.employees[i], { dep_id: 0, dep_name: this.dep_name });
  }
}

var mapE = function() {
  for (var i=0; i<this.departments.length; i++) {
    emit(this._id, { dep_id: this.departments[i].dep_id, dep_name: 0 });
  }
}

var reduceLookUp = function(key, values) {
  var result = {dep_id: 0, dep_name: 0};
  values.forEach(function(value) {
    if (value.dep_name !== null && value.dep_name !== undefined) {
      result.dep_name = values.dep_name;
    }
    if (value.dep_id !== null && value.dep_id !== undefined) {
      result.dep_id = value.dep_id;
    }
  });
  return result;
};

db.Departments.mapReduce(mapD, reduceLookUp, { out: { reduce: "joined" } });
db.Employees.mapReduce(mapE, reduceLookUp, { out: { reduce: "joined" } });

我将非常感谢你的帮助!提前致谢。


在你的问题中first_name只能从Employees收集和dep_name只能从Departments收藏。

您可以使用 MapReduce 和聚合框架来实现它。

1.MapReduce解决方案

如果你修改你的map和reduce函数如下

var mapD = function() {
  for (var i=0; i<this.employees.length; i++)
    emit(this.employees[i], { dep_id: this._id, dep_name: this.dep_name });  
}

var mapE = function() { emit(this._id, { first_name: this.first_name }); }

var reduceLookUp = function(key, values) {
  var results = {};
  var departments = [];
  values.forEach(function(value) {
    var department = {};
    if (value.dep_id !== undefined) department["dep_id"] = value.dep_id;
    if (value.dep_name !== undefined) department["dep_name"] = value.dep_name;
    if (Object.keys(department).length > 0) departments.push(department);
    if (value.first_name !== undefined) results["first_name"] = value.first_name;
    if (value.departments !== undefined) results["departments"] = value.departments;
  });
  if (Object.keys(departments).length > 0) results["departments"] = departments;
  return results;
}

然后首先调用 MapReduce

db.Departments.mapReduce(mapD, reduceLookUp, { out: { reduce: "joined" } });

将插入到joined收藏

{ 
  "_id" : "1234", 
  "value" : 
  {
    "departments" : 
    [ 
      { "dep_id" : "d001", "dep_name" : "Sales" }, 
      { "dep_id" : "d004", "dep_name" : "Quality M" } 
    ] 
  }
}

当第二次通话时

db.Employees.mapReduce(mapE, reduceLookUp, { out: { reduce: "joined" } });

应该插入

{ "_id" : "1234", "value" : { "first_name" : "John" } }

但是,根据文档 https://docs.mongodb.com/manual/reference/command/mapReduce/#out-options, reduce输出选项将

如果输出集合,则将新结果与现有结果合并 已经存在。如果现有文档与新文档具有相同的密钥 结果,将reduce函数应用于新的和现有的 文档并用结果覆盖现有文档

因此,在您的情况下,将使用参数再次调用reduce函数

key = "1234",
values =
[
  {
    "departments" : 
    [ 
      { "dep_id" : "d001", "dep_name" : "Sales" }, 
      { "dep_id" : "d004", "dep_name" : "Quality M" } 
    ] 
  },
  { "first_name" : "John" }
]

最终结果是

{ 
  "_id" : "1234", 
  "value" : 
  { 
    "first_name" : "John", 
    "departments" : 
    [ 
      { "dep_id" : "d001", "dep_name" : "Sales" }, 
      { "dep_id" : "d004", "dep_name" : "Quality M" }
    ] 
  } 
}

2.聚合框架方案

解决您问题的更好方法是使用聚合框架 https://docs.mongodb.com/manual/aggregation/而不是 Map-Reduce。在这里你会使用$lookup https://docs.mongodb.com/manual/reference/operator/aggregation/lookup/从中获取一些数据的阶段Employees

db.Departments.aggregate([
  { $unwind: "$employees" },
  { 
    $lookup: 
      { 
        from: "Employees", 
        localField: "employees", 
        foreignField: "_id", 
        as: "employee"
      }
  },
  { $unwind: "$employee" },
  { 
    $group: 
      { 
        "_id": "$employees",
        "first_name": { $first: "$employee.first_name" }, 
        "departments": { $push: { dep_id: "$_id", dep_name: "$dep_name" } } 
      } 
  } 
]);

这将导致

{ 
  "_id" : "1234",
  "first_name" : "John",
  "departments" : 
    [ 
      { "dep_id" : "d001", "dep_name" : "Sales" }, 
      { "dep_id" : "d004", "dep_name" : "Quality M" } 
    ] 
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 MongoDB 中使用 MapReduce 连接两个集合 的相关文章

  • 重命名($project)数组中的字段 - MongoDB [重复]

    这个问题在这里已经有答案了 我有一个类似以下的文件 id 59ba903dacea50d0d7d47168 sections id 59d9dd7947ce651544c5d4c1 sectionName Section 1 id 59d9
  • SQL:列出多个连接语句中的重复记录?

    你好 以下查询在连接多个表后返回所有员工 select e from dbo EMP e join dbo HREMP a on a ID e ID join dbo LOGO c on c EMPID e id join dbo LOGO
  • MongoDB 使用 $sort、$skip 和 $limit 返回错误的行

    这是我正在使用的功能 MyModel aggregate match query sort createdAt 1 skip skip limit 10 allowDiskUse true query是过滤行 skip是基于分页的动态值 即
  • Android - 如何合并两个视频

    基本上 我正在寻找一种将两个 mp4 视频文件 在 SD 卡上 组合在一起的方法 更像是在第一个视频的末尾附加第二个视频 我进行了很多搜索 但找不到合适的解决方案 好吧 我根本找不到任何解决方案 所以我的问题是 是否有一个库可以组合 并可能
  • MongoDB C# 驱动程序“找不到光标”

    我有一个相当密集的操作MongoCursor循环运行几个小时 在通过 c 驱动程序运行的 vb net 应用程序上 我不太确定是什么导致了它 但一段时间后我遇到了异常 Cursor not found 这可能是由于游标超时造成的 有什么办法
  • 动态/条件 SQL 连接?

    我在 MSSQL 表 TableB 中有数据 其中 dbo tableB myColumn 在特定日期后更改格式 我正在做一个简单的连接到该表 Select dbo tableB theColumnINeed from dbo tableA
  • mongodb - 检索数组子集

    看似简单的任务对我来说是一个挑战 我有以下 mongodb 结构 services TCP80 data status 1 delay 3 87 ts 1308056460 status 1 delay 2 83 ts 1308058080
  • 使用 dockerfile 在 docker 中安装 mongodb 驱动

    我有一个 mongodb docker 容器 我需要另一个安装了 php 和 apache 的 docker 容器 我想从这个容器运行一个 php 脚本并将一些数据发送到 mongodb 容器以将数据保存在 mongodb 数据库中 所以我
  • 如何使用c#从数据桶中获取所有文档?

    如何获取数据桶中的所有文档 我尝试过一个示例 但我只能获得一个特定的文档 这是我的代码 CouchbaseClient oclient oclient new CouchbaseClient vwspace data bucket name
  • mocha——手表和猫鼬模型

    如果我让 mocha 监视更改 每次保存文件时 mongoose 都会抛出以下错误 OverwriteModelError 无法覆盖Client模型一旦编译 我知道猫鼬不允许两次定义模型 但我不知道如何让它与mocha watch clie
  • 删除重复的 SQL 记录以允许唯一键

    我在 MYSQL 数据库中有一个表 销售 该表理应强制执行唯一约束以防止重复 事实证明 首先删除欺骗并设置约束有点棘手 表结构 简化 id 唯一 autoinc 产品编号 目标是强制product id 的唯一性 我想要应用的重复数据删除策
  • 在 PowerShell 中,将两个表合并为一个表的最佳方法是什么?

    我对 PowerShell 相当陌生 想知道是否有人知道解决以下示例问题的更好方法 我有一组从 IP 地址到主机名的映射 这表示活动 DHCP 租约的列表 PS H gt leases IP Name 192 168 1 1 Apple 1
  • 使用子查询与 LEFT JOIN 一起选择 MAX 值

    我有一个获取搜索结果的查询 效果很好 查询成功示例 SELECT individuals individual id individuals unique id TIMESTAMPDIFF YEAR individuals day of b
  • 在 Windows 7 - 64 位上安装 Mongodb

    我是 mongodb 的新手 不知道如何安装它 因为我找不到视频或任何有用的资源来实现相同的目的 请帮助我在 Windows 7 上安装 mongodb 并提供确切的步骤 我尝试从该网站下载最新版本的 mongodb 但不成功 提前致谢 R
  • 我可以要求在 mongodb 集合中设置属性吗? (不为空)

    我可以在 mongodb 中定义一个需要设置某些属性的模式吗 很像NOT NULL在 SQL 中 如果可以的话 这个的语法是什么 我正在使用 Node js 和猫鼬 猫鼬 v3 6 15 MongoDB v2 4 5 EditCharles
  • i18Next - NodeJS - 如何在不重新加载服务器的情况下更改翻译

    我正在使用 NodeJS 的 i18next 包来启用翻译 我将它作为标准 并为每个语言 国家对使用一个 json 文件 我想构建一个管理页面来编辑翻译 而无需深入研究代码 那么 如何 重新加载 管理员编辑过的 json 文件 而无需重新启
  • CoreMongooseArray 到普通数组

    我正在从一个架构中选出 2 个元素 并希望在另一个架构中进行更新 为此 我使用切片方法将数组中的前 2 个元素列入候选名单 但我越来越 CoreMongooseArray 元素1 元素2 而不是 元素1 元素2 如何删除 CoreMongo
  • 强力查询历年产品利润对比

    我有一个数据集 其中包含公司 产品 利润和年份 公司每年都会销售少量产品并获得利润 公司没有必要在明年销售相同的产品 他们可能会省略以前的产品并添加新的少量产品 我只想对两年的产品进行逐个比较 如下所示 我的数据集是 Company Pro
  • Mongoid 命名范围比较同一文档中的两个时间字段

    我需要在 Mongoid 中创建一个命名范围来比较同一文档中的两个时间字段 例如 scope foo where gt updated at gt gt checked at 这显然不会像它对待的那样起作用 checked at作为一个符号
  • SQL中如何合并多个表的数据

    我想我的处境很复杂 这是场景 我在 SQL Server 中有 3 个表 注册 学生 课程 仅供参考 没有外键 表的列是 Student 学生号 学生名 Course 课程 ID 课程名称 注册 注册 ID 学生 ID 课程 ID 课程结果

随机推荐