美文网首页
Mongo连表聚合查询(1)

Mongo连表聚合查询(1)

作者: 我爱张智容 | 来源:发表于2021-06-19 16:36 被阅读0次

在使用MongoDB存储数据的时候,我们查询的时候,有时候难免会需要进行连表查询。但是MongoDB本身是非关系性数据库,连表查询,很多时候,需要我们自己在代码里手工操作。但是从 MongoDB 3.2 版本过后,我们可以使用 lookup 进行连表查询。下面就简单介绍一下 MongoDB 的lookup 的简单使用。

比如现在我们有两张表, user 和 order 表。
其中 user 表中的字段有 _id、uid、name、age;
order 表中的字段有:_id、uid、product、money;

两张表存储的数据为:

users = [{
  _id: ObjectId("5af2b2c6b138c267e414c072"),
  uid: "uid000",
  name: "小A",
  age: 26
}, {
  _id: ObjectId("5af2b2c6b138c267e414c073"),
  uid: "uid001",
  name: "小B",
  age: 27
}]
 
orders = [{
  _id: ObjectId("4af2b2c6b138c267e414c071"),
  uid: "uid000",
  product: "产品1",
  money: 100
}, {
  _id: ObjectId("4af2b2c6b138c267e414c072"),
  uid: "uid000",
  product: "产品2",
  money: 200
}, {
  _id: ObjectId("4af2b2c6b138c267e414c073"),
  uid: "uid001",
  product: "产品1",
  money: 100
}, {
  _id: ObjectId("4af2b2c6b138c267e414c074"),
  uid: "uid001",
  product: "产品2",
  money: 200
}]

假如现在有两个需求:

查询用户信息并且显示该用户的总消费金额(用户名、年龄、总消费金额)
查询用户的订单信息(订单id、产品、价格、用户名)

  1. 首先来看第一个需求:
     这个需求如果我们不考虑连表,只考虑关联的话,应该是

先查询出用户表所有的数据
在订单表中求出每一个用户的消费总金额
遍历用户和订单数据,然后一一通过 uid 进行匹配对应。
 如果按照我们的数据库连表来说:那应该是我们查询 user 表关联到 order 表,然后分组根据 uid 统计求和;下面来看一看具体的实现方式。

1.1 连表查询

db.user.aggregate([{
  $lookup: { // 左连接
    from: "order", // 关联到order表
    localField: "uid", // user 表关联的字段
    foreignField: "uid", // order 表关联的字段
    as: "orders"
  }
}]);

这个时候出来的结果应该为:

users = [{
  _id: ObjectId("5af2b2c6b138c267e414c072"),
  uid: "uid000",
  name: "小A",
  age: 26,
  orders: [{
    _id: ObjectId("4af2b2c6b138c267e414c071"),
    uid: "uid000",
    product: "产品1",
    money: 100
  }, {
    _id: ObjectId("4af2b2c6b138c267e414c072"),
    uid: "uid000",
    product: "产品2",
    money: 200
  }]
}, {
  _id: ObjectId("5af2b2c6b138c267e414c073"),
  uid: "uid001",
  name: "小B",
  age: 27,
  orders: [{
    _id: ObjectId("4af2b2c6b138c267e414c073"),
    uid: "uid001",
    product: "产品1",
    money: 100
  }, {
    _id: ObjectId("4af2b2c6b138c267e414c073"),
    uid: "uid001",
    product: "产品1",
    money: 200
  }]
}]

1.2 拆分 orders 数组

{
  $unwind: { // 拆分子数组
    path: "$orders",
    preserveNullAndEmptyArrays: true // 空的数组也拆分
  }
}

这个时候的数据结果应该是这样的

[{
  _id: ObjectId("5af2b2c6b138c267e414c072"),
  uid: "uid000",
  name: "小A",
  age: 26,
  orders: {
    _id: ObjectId("4af2b2c6b138c267e414c071"),
    uid: "uid000",
    product: "产品1",
    money: 100
  }
}, {
  _id: ObjectId("5af2b2c6b138c267e414c072"),
  uid: "uid000",
  name: "小A",
  age: 26,
  orders: {
    _id: ObjectId("4af2b2c6b138c267e414c072"),
    uid: "uid000",
    product: "产品2",
    money: 200
  }
} …… ]

1.3 分组求和并返回字段数据

{
  $group: { // 分组查询
    _id: "$_id",
    name: { $first: "$name" },
    age: { $first: "$age" },
    money: {$sum: "$orders.money"}
  }
}

这样就查询出了我们所需要的数据。
将代码总结一下为:

db.user.aggregate([{
  $lookup: { // 左连接
    from: "order", // 关联到order表
    localField: "uid", // user 表关联的字段
    foreignField: "uid", // order 表关联的字段
    as: "orders"
  }
}, {
  $unwind: { // 拆分子数组
    path: "$orders",
    preserveNullAndEmptyArrays: true // 空的数组也拆分
  }
}, { // 分组求和并返回
  $group: { // 分组查询
    _id: "$_id",
    name: { $first: "$name" },
    age: { $first: "$age" },
    money: {$sum: "$orders.money"}
  }
}]);
  1. 查询用户的订单信息
    2.1 连表查询
    这个时候的连表是 order 表 跟 user 表关联(上一个是 user 表 和 order 表关联)
{
  $lookup: {
    from: "users",
    localField: "openid",
    foreignField: "openid",
    as: "u"
  }
}

2.2 拆分子数组

{ $unwind: "$u" }

2.3 只返回需要的字段
将 user 中需要返回的字段,提到子目录来

{$addFields: {  name: "$u.name" }}

2.4 返回最终需要的字段结果

{ 
  $project: {
    _id: 1,
    product: 1,
    money: 1,
    name: 1
  }
}

最终的代码为:

db.order.aggregate([{
  $lookup: {
    from: "users",
    localField: "openid",
    foreignField: "openid",
    as: "u"
  }
}, {
  $unwind: "$u"
}, {
  $addFields: {  name: "$u.name" }
}, {
  $project: {
    _id: 1,
    product: 1,
    money: 1,
    name: 1
  }
}]);

虽然在 MongoDB 3.2 后我们能够进行连表查询了,方便了很多。
但是其实 MongoDB本身是非关系性数据库。如果需要进行频繁的这种连表查询,我们可以考虑优化我们的数据库表。
比如在订单表里面,每一条的订单记录都把我们的用户信息放进去。

[{
  _id: ObjectId("4af2b2c6b138c267e414c071"),
  uid: "uid000",
  product: "产品1",
  money: 100,
  user: {
    _id: ObjectId("5af2b2c6b138c267e414c072"),
    uid: "uid000",
    name: "小A",
    age: 26
  }
}, {
  _id: ObjectId("4af2b2c6b138c267e414c071"),
  uid: "uid000",
  product: "产品1",
  money: 100,
  user: {
    _id: ObjectId("5af2b2c6b138c267e414c072"),
    uid: "uid000",
    name: "小A",
    age: 26
  }
}]

这个时候,在实现两个需求就很简单了:

// 1. 查询用户信息并且显示该用户的总消费金额(用户名、年龄、总消费金额)

db.order.aggregate([{ 
// 根据 uid 求和
  $group: {
    _id: '$user.uid',
    money: {
      $sum: "$money"
    },
    name: { $first: "$user.name" },
    age: { $first: "$user.age" }
  }
}]);

// 2. 查询用户的订单信息(订单id、产品、价格、用户名)

db.order.aggregate([{
  {$addFields: {  name: "$user.name" }}
}, { // 根据 uid 求和
  $project: {
    _id: 1,
    money: 1,
    product: 1,
    name: 1
  }
}]);

相关文章

  • Mongo连表聚合查询(1)

    在使用MongoDB存储数据的时候,我们查询的时候,有时候难免会需要进行连表查询。但是MongoDB本身是非关系性...

  • mongo聚合查询

    1.概述 MongoDB 聚合框架(Aggregation Framework)是一个计算框架,它可以:• 作用在...

  • Mongodb 的高级查询

    关键词:mongodb, mongo, project, group, aggregate, 聚合管道, 高级查询...

  • sql _ 连表查询 & 授权

    一,连表查询 1)连表 简单查询_where 2) 连表 多种方式查询 3)子查询 综合以上查询示例 二,DCL数...

  • [日记]Mongo聚合查询

    collection 1 使用mongo查询一个对象数组中元素属性为特定值的数据,期望查询结果为: 语句: 2 若...

  • 多表关联查询定义,种类

    关联查询:连接查询、子查询、聚合查询 1.连接查询. 左外连结 左表的全部记录(部门表中的所有记录:demp方式1...

  • mongo $match查询日期结果错误

    今天使用mongo聚合查询某个时间段的数据 发现返回结果错误 经过排查问题 在聚合中$match查询和平常使用fi...

  • mongo回顾(八:聚合查询二)

    上一篇简单的介绍了mongo的聚合查询,并举例了match与lookup的使用,今天的话继续介绍聚合查询与Mong...

  • Django 中的聚合查询与分组查询

    聚合 常用的聚合函数 Avg, Max, Min 实例1 实例2 分组 emp表模型 总结 :跨表分组查询本质就...

  • 《SQL基础教程》学习笔记Ch3

    3聚合与排序 3-1对表进行聚合查询 聚合函数 COUNT:计算表中的记录数(行数)SUM:计算表中数值列中数据的...

网友评论

      本文标题:Mongo连表聚合查询(1)

      本文链接:https://www.haomeiwen.com/subject/pprlyltx.html