今天在写一个微信小程序demo,用的是云开发,是一个实验室预约的一个流程。一开始写的很开心,毕竟用java ssm+mysql简单的一笔。心里想着云数据库不也差不多嘛。但是后来发现差距蛮大的,不过还好,只要熟练数据库,对于这个还是看看API文档还是能够轻松上手的。但是貌似度娘以及小程序云开发社区对于这个多表联查的具体使用几乎没有,API文档其实对于新手而言难度还是比较大的,也很难找到教学,所以我这里讲解一下。废话不多说,上代码。

我总共有三个表:用户表,实验室表,审批表

用户表的数据是这样的:

{
    "_id":"f149f6775e9d6ec600876c1a16ced8c8", //这个是云数据库自动生成的id
    "u_account":"asd",
    "u_name":"学生1",
    "u_password":"123",
    "u_role":0
}



我的实验室表是这样的:

{
    "_id":"0d9cdb685e9d8354007a2b0e376d0d73",
    "l_name":"实验室C",
    "l_manager":"负责人3",
    "l_address":"教学楼C202",
    "l_status":"可预约"
}

我的审批表是这样的:

{
    "_id":"f149f6775e9dabd10090e4d452807018",
    "u_account":"asd",
    "l_id":"0d9cdb685e9d8354007a2b0e376d0d73",
    "a_status":"待审核",
    "a_date":"2020-04-18 20:59"
}

接下来就是希望这三张表联查,并且把字段合并

1. 先看两张表联查

小程序官方文档写的很明确,想要联查用聚合

API地址: 联表查询 | 微信开放文档

2.先把审批表和用户表关联查询

// 云函数入口函数
exports.main = async (event, context) => {
  return cloud.database().collection("tb_approval").aggregate() //选择我的审批表
          .lookup({
            from:"tb_user", //把tb_user用户表关联上
            localField: 'u_account', //审批表的关联字段
            foreignField: 'u_account', //用户表的关联字段
            as: 'uapproval' //匹配的结果作为uapproval相当于起个别名
          }).end({
            success:function(res){
              return res;
            },
            fail(error) {
              return error;
            }
          })
}

输出的结果是这样的:

{
    _id:"f149f6775e9dabd10090e4d452807018",
    u_account:"asd",
    l_id:"0d9cdb685e9d8354007a2b0e376d0d73",
    a_status:"待审核",
    a_date:"2020-04-18 20:59",
    uapproval:[
        {
            _id:"f149f6775e9d6ec600876c1a16ced8c8",
            u_account:"asd",
            u_name:"学生1",
            u_password:"123",
            u_role:0
        }
    ]
}

3. 修改返回结果

呐,这不是联查出来的,等等别急,我知道这不是你想要的,你想要的是这样的:

{
    _id:"f149f6775e9dabd10090e4d452807018",
    u_account:"asd",
    l_id:"0d9cdb685e9d8354007a2b0e376d0d73",
    a_status:"待审核",
    a_date:"2020-04-18 20:59",
    u_name:"学生1",
    u_password:"123",
    u_role:0
}

怎么做呢,需要用到replaceRoot,newRoot,project。这三个的用法自己看API了哈

把云函数改成这样既可有上面的效果

var $ = cloud.database().command.aggregate   //定义聚合操作符
// 云函数入口函数
exports.main = async (event, context) => {
  return cloud.database().collection("tb_approval").aggregate()
          .lookup({
            from:"tb_user",
            localField: 'u_account',
            foreignField: 'u_account',
            as: 'uapproval'
          })
          .replaceRoot({  
 
            //replaceRoot指定一个已有字段作为输出的根节点,也可以指定一个计算出的新字段作为根节点。
           //newRoot  代表新的根节点
 
            newRoot: $.mergeObjects([$.arrayElemAt(['$uapproval', 0]), '$$ROOT'])
            
            //mergeObjects 累计器操作符
            //$.mergeObjects([params1,params2...]) 可以合并多个元素
            //$.arrayElemAt(['$uapproval', 0]), '$$ROOT']
            //就是取uapproval数组的第一个元素,与原始的根融合在一起
            
          })
          .project({
            //project把指定的字段传递给下一个流水线,指定的字段可以是某个已经存在的字段,也可以是计算出来的新字段
            uapproval: 0
          })
          .end({
            success:function(res){
              return res;
            },
            fail(error) {
              return error;
            }
          })
}

这样就可以返回上面那样的数据了。但是这里只是两张表的联查啊。别急,三张表的出炉了

4. 三表联查

var $ = cloud.database().command.aggregate
// 云函数入口函数
exports.main = async (event, context) => {
  return cloud.database().collection("tb_approval").aggregate()
    .lookup({
      from: "tb_user",
      localField: 'u_account',
      foreignField: 'u_account',
      as: 'uapproval'
    })
    .lookup({
      from: "tb_lab",
      localField: 'l_id',
      foreignField: '_id',
      as: 'lapproval'
    })
    .replaceRoot({
      newRoot: $.mergeObjects([$.arrayElemAt(['$uapproval', 0]), $.arrayElemAt(['$lapproval', 0]), '$$ROOT'])
    })
    .project({
      uapproval: 0,
      lapproval: 0
    })
    .end({
      success: function (res) {
        return res;
      },
      fail(error) {
        return error;
      }
    })
}

返回的数据是这样的:

{
    _id:"f149f6775e9dabd10090e4d452807018",
    u_account:"asd",
    u_name:"学生1",
    u_password:"123",
    u_role:0,
    l_id:"0d9cdb685e9d8354007a2b0e376d0d73",
    l_name:"实验室C"
    l_address:"教学楼C202",
    l_manager:"负责人3",
    l_status:"可预约",
    a_status:"待审核",
    a_date:"2020-04-18 20:59"
}

这样一来,三张表的联查是不是就看懂了。既然如此,那更多的表不都是可以轻而易举了。看大家都没有发过这样的讲解说明博客,所以我发一个,这样让别人少走弯路。


以上为转载的原文,看了有评论问的问题,我自己去试了一下还是可以跑起来,原文代码里面有逗号是全角的已经修改。

验证步骤也挺简单的:

一、先在云数据库建3个数据集,名称如文章中的:tb_user tb_lab tb_approval

二、填入测试数据,就是开始的3个json代码里面内容,把_id去掉,会自动生成

三、新建Node.js云函数(不会的可能要查下,不铺开讲了)

四、复制4.三表联查那段的代码进去。

五、上传部署云函数,部署好就可以在云函数看到这个函数。点云端测试后在日志就能找到如下:

日志内容 Request ID: c7a90567-f0f0-4636-a484-a7108968e59a
执行时间: 64ms内存使用: 23.90 MB
返回结果
{"list":[{"_id":"0ab5303b6289a1ec0526e2036ad6b9b8","u_account":"asd","u_name":"张三","u_password":"123","u_role":0,"a_date":"2020-04-18 20:59","a_status":"待审核","l_id":"0d9cdb685e9d8354007a2b0e376d0d73"}],"errMsg":"collection.aggregate:ok"}

日志
START
当前未指定env,将默认使用第一个创建的环境!
REPORT RequestId:c7a90567-f0f0-4636-a484-a7108968e59a Duration:64ms Memory:256MB MemUsage:23.899879MB
END