收藏
回答

lookup联查如何不返回右表为空的主表数据?

  let openid=cloud.getWXContext().OPENID
  const db = cloud.database()
  const $ = db.command.aggregate
  const _ = db.command
  return await db.collection('goods_list').aggregate()
    .match({
      goodsFlag:'1'
    })
    .lookup({
      from'tuan_list',
      let: {
        goods_id:'$_id'
      },
      pipeline: $.pipeline()
        .match(_.expr($.and([
          $.eq(['$tuanZhangOpenId',openid]),
          $.neq(['$goodsId','$$goods_id'])
        ])))
        .project({
          _id:0,
          goodsList:$.eq(['$goodsList'.length,0]),
          tuanZhangOpenId:1,
          goodsId:1
        })
        .done(),
      as'goodsList',
    })
    .end()
    .then(res => res)
    .catch(err => res)

数据结构:

goods_list(只有两条数据)

tuan_list(只有一条数据)

===========================

返回结果:

疑问:

在我的pipeline的match中,条件控制项,ID要求不相等的这个$.neq(['$goodsId','$$goods_id'])未起到作用吗?

还是说理论上子表的条件不优先?

需求结果:

result只返回goodsList有值的结果,即“牛肉”的那条数据。

PS:除了在then里写JS循环判断再重新push后return这种方式,可不可以在match里或其他项上做条件控制?

感谢。

-

如果我用sql写的话,思路是下面这样:

SELECT a.* from a left join b 

on b.aid!=a.id

where a.goodsFlag=1 and b.aid is not null

在微信云开发中,第一个match的条件,是先执行再lookup,还是先lookup再执行第一个match?

如果我想判断goodsList数组的长度,我尝试过在第一个match里追加goodsList:$.eq(['$goodsList'.length,0]),但失败了。

所以是不是第一个match要先于lookup呢?

我在lookup之后match去判断数组长度,好像也没起到作用。

-

另外,如果lookup的左外联性质,无法改变,它不能像sql一样在最外集合追加where 子表 is not null的话,我想我可能要改变表结构了。

那么,如果我使用文档型数据库的话,单条数据的goodsList字段[],存放过多的集合,会不会对查询造成压力。

比如:

{goodsName:测试商品, goodsPrice:10.00, tuanList[1,2,3,4,5……10000]}

当我去筛选某些值 in tuanList的时候,效率高吗?

不太了解云开发的数据库效率。

在云开发数据库中,是不是更倾向于文档型结构?传统的关系型结构,反而会带来麻烦和效率问题呢?

最后一次编辑于  2020-12-17
回答关注问题邀请回答
收藏

1 个回答

  • 乔
    2020-12-17

    呃。。。

    按照传统SQL去套,最后弄明白了。

    首先数组的关键字错了,用_.size()是正确的。

    其次,要在最后lookup后再match goodsList:_.size(1)

    (我用size1是为了方便,实际情况肯定不止1,可以再套个gt试试,另外,官方文档中,对match提到:注意 match 阶段和其他聚合阶段不同,不可使用聚合操作符,只能使用查询操作符。所以如果要用聚合函数,需要_.expr吧,就像pipeline里一样,我还没有试,遇到同样问题的伙伴,自己试一下吧

    然后成功了。

    虽然成功了,但我决定还是要重新设计数据结构。

    我认为这种效率应该真的不高,大家可以查看日志里的内存性能损耗,看自己的业务执行情况。

    最后:

    第一次开发小程序,也从没用过vue或者node。

    这种磕磕绊绊的尝试,才能对比出与java和jsp的区别吧,印象才深刻。

    代码如下(格式不整齐,有一些冗余的,有一些无效的,请忽略,我也在尝试的路上):

    const openid=cloud.getWXContext().OPENID
      const db = cloud.database()
      const $ = db.command.aggregate
      const _ = db.command
      return await db.collection('goods_list').aggregate()
        .match({
          goodsFlag:'1'
        })
        .lookup({
          from'tuan_list',
          let: {
            goods_id:'$_id',
            oid:openid
          },
          pipeline: $.pipeline()
            .match(_.expr($.and([
              $.eq(['$tuanZhangOpenId','$$oid']),
              $.neq(['$goodsId','$$goods_id'])
            ])))
            .project({
              _id:0,
              goodsList:$.eq(['$goodsList'.length,0]),
              tuanZhangOpenId:1,
              goodsId:1
            })
            .done(),
          as'goodsList',
        })
        .match({
          goodsList:_.size(1)
        })
    
    
        .end()
        .then(res => res)
        .catch(err => res)
        
        // return res
    }
    

    我看这个帖子浏览量也不低,估计还有一些刚接触的伙伴,遇到了同样的问题,解决过程中不断的搜帖子,我作为一个小程序新手,尽量帮其他新手留下一些痕迹吧,也为其他老手留下更多时间,解决非这种low的问题或帖子。

    经验标注:

    1.小程序数据结构很关键;

    2.官方文档要看,但更重要的是自己的思维。

    3.有其他开发基础,尤其是数据库的,发散思维结合经验。

    4.无经验的,还是多搜帖子多看多问吧。

    2020-12-17
    有用 3
    回复 4
    • 彬Ben
      彬Ben
      发表于小程序端
      2020-12-17
      在前端不是不能使用lookup吗?您能成功使用lookup?
      2020-12-17
      回复
    • 乔
      2020-12-18回复彬Ben
      不是在前端,是在云函数中使用的。
      2020-12-18
      回复
    • 乔
      2020-12-18回复彬Ben
      我理解前端单表查询,联查需要云函数的一个原因,就是小程序数据库设定类型决定的,它的目应该就是让我们尽量遵守文档型数据结构来做开发吧,提升效率,减少无必要的查询。所以当遇到需要lookup时,有的时候可能是真需要Lookup,有的时候可能是我们对表的设计有了偏差。不过现在我还没搞清楚,一条数据中的一个字段,可以包含多少个数组,我记得之前有前辈说是1m的数据量。我继续在看文档和写测试。
      2020-12-18
      回复
    • 千行
      千行
      2021-08-26
      谢谢答主,今天正好再为lookup返回的空数组头疼呢,原来在后面加一个 size 就可以了
      2021-08-26
      回复
登录 后发表内容
问题标签