mongodb联表查询_mongodb聚合查询

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

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

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

  比如现在我们有两张表, userorder 表。其中 user 表中的字段有 _iduidnameageorder 表中的字段有:_iduidproductmoney; 两张表存储的数据为:

users = [{
  _id: ObjectId("5af2b2c6b138c267e414c072"), uid: "uid000", name: "小红", age: 26 }, { _id: ObjectId("5af2b2c6b138c267e414c073"), uid: "uid001", name: "小芳", 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 }]

假如现在有两个需求:

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

1. 首先来看第一个需求:

 这个需求如果我们不考虑连表,只考虑关联的话,应该是

  1. 先查询出用户表所有的数据
  2. 在订单表中求出每一个用户的消费总金额
  3. 遍历用户和订单数据,然后一一通过 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: "小红", 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: "小芳", 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: "小红",
  age: 26,
  orders: {
    _id: ObjectId("4af2b2c6b138c267e414c071"),
    uid: "uid000",
    product: "产品1",
    money: 100
  }
}, {
  _id: ObjectId("5af2b2c6b138c267e414c072"),
  uid: "uid000",
  name: "小红",
  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"}
  }
}]);

2. 查询用户的订单信息

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: "小红",
    age: 26
  }
}, {
  _id: ObjectId("4af2b2c6b138c267e414c071"),
  uid: "uid000",
  product: "产品1",
  money: 100,
  user: {
    _id: ObjectId("5af2b2c6b138c267e414c072"),
    uid: "uid000",
    name: "小红",
    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
  }
}]);
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/194012.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • pycharm中unresolvedreference_pycharm add new configuration

    pycharm中unresolvedreference_pycharm add new configuration在用Pycharm写项目的时候的时候碰到一个很无语的问题路径明明没有问题,运行也没有出错,但就是爆红,逼死强迫症啊。。。多方查找最后解决了。步骤如下:File–>Settings–>ProjectStructure–>找到问题目录–>Sources–>Apply–>OKOK了,不在爆红…

    2022年8月26日
    4
  • java+widthstep_关于IplImage中widthstep的大小与width,nchannels等的关系的问题

    java+widthstep_关于IplImage中widthstep的大小与width,nchannels等的关系的问题width是图像宽度,可为任意值;widthstep是行字节数,应该是4的倍数,不一定等于width,nchannels为图像通道数。#defineWIDTHBYTES(bits)(((bits)+31)/32*4)看看这个公式你就明白了。对ROI和widthStep的补充ROI和widthStep在实际工作中有很重要的作用,在很多情况下,使用它们会提高计算机视觉代码的执行速度。这是因为它们…

    2022年6月4日
    32
  • 2010-11-12 股市地动山摇 却未到泡沫破裂时

    2010-11-12 股市地动山摇 却未到泡沫破裂时

    2021年8月8日
    74
  • 搞定Android开发环境部署——非常详细的Android开发环境搭建教程[通俗易懂]

    搞定Android开发环境部署——非常详细的Android开发环境搭建教程[通俗易懂]引言在windows安装Android的开发环境不简单也说不上算复杂,本文写给第一次想在自己Windows上建立Android开发环境投入Android浪潮的朋友们,为了确保大家能顺利完成开发环境的搭建,文章写的尽量详细,希望对准备进入Android开发的朋友有帮助。 Android开发环境搭建分为以下四步:第一步、安装JDK;第二步、安装Eclipse;第三步、下载并

    2022年7月23日
    12
  • Ubuntu安装gcc-7.3.0[通俗易懂]

    Ubuntu安装gcc-7.3.0[通俗易懂]下载gcc-7.3.0.tar.gzfromhttps://mirrors.tuna.tsinghua.edu.cn/gnu/gcc/gcc-7.3.0/gcc-7.3.0.tar.gz.有一些依赖提前安装:sudoaptinstalllibgmp-devsudoaptinstalllibmpfr-devsudoaptinstalllibmpc-devsudoaptinstalllibisl-devsudoaptinstallzlib1g-dev(建.

    2022年7月24日
    25
  • python生成器详解_自动生成python代码

    python生成器详解_自动生成python代码生成器利用迭代器,我们可以在每次迭代获取数据(通过next()方法)时按照特定的规律进行生成。但是我们在实现一个迭代器时,关于当前迭代到的状态需要我们自己记录,进而才能根据当前状态生成下一个数据。

    2022年7月31日
    54

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号