收藏
回答

lookup联表查询,需要分页查询时,如何用简洁的代码获取文档总数count?

在分页查询中,一般是需要返回符合条件的文档总数的,下面的代码是先获取文档总数count,然后获取0-20条数据。这两部分的代码高度重复,如果查询条件复杂的话,更是十分冗长。

  // 文档总数量count读取
    let queryCount = db.collection('cats-order').aggregate()
  .match(orderMatch)
  .project({
    shopId: true,
    customerId: true,
    status: true,
    services: true,
    createTime: true,
  })
  .lookup({
    from'cats-shop',
    let : {
      shopId: '$shopId'
    },
    pipeline: $.pipeline()
    .match(_.expr($.and([
      $.eq(['$_id''$$shopId'])
    ])))
    .project({
      _id: false,
      shopTitle: '$title'
    })
    .done(),
    as'shops'
  })
  .replaceRoot({
    newRoot: $.mergeObjects([$.arrayElemAt(['$shops'0]), '$$ROOT'])
  })
  .project({
    shops: false
  })
  .lookup({
    from'cats-customer',
    let: {
      customerId: '$customerId'
    },
    pipeline: $.pipeline()
    .match(_.expr($.and([
      $.eq(['$_id''$$customerId'])
    ]))).project({
      _id: false,
      customerTitle: '$title',
      customerPhone: '$phone',
      customerLevel: '$level'
    }).done(),
    as'customers'
  })
  .replaceRoot({
    newRoot: $.mergeObjects([$.arrayElemAt(['$customers'0]), '$$ROOT'])
  })
  .project({
    customers: false
  })
  if (searchWord) {
    queryCount = queryCount.match(_.or([{
      customerTitle: new RegExp(searchWord, 'i')
    }, {
      customerPhone: new RegExp(searchWord, 'i')
    }]))
  }
  let countRes = await queryCount.count('total').end()
  pager.Total = countRes.list[0].total

    // 分页数据读取
  let queryList = db.collection('cats-order').aggregate()
  .match(orderMatch)
  .project({
    shopId: true,
    customerId: true,
    status: true,
    services: true,
    createTime: true,
  })
  .lookup({
    from'cats-department',
    let : {
      shopId: '$shopId'
    },
    pipeline: $.pipeline()
    .match(_.expr($.and([
      $.eq(['$_id''$$shopId'])
    ])))
    .project({
      _id: false,
      shopTitle: '$title'
    })
    .done(),
    as'shops'
  })
  .replaceRoot({
    newRoot: $.mergeObjects([$.arrayElemAt(['$shops'0]), '$$ROOT'])
  })
  .project({
    shops: false
  })
  .lookup({
    from'cats-customer',
    let: {
      customerId: '$customerId'
    },
    pipeline: $.pipeline()
    .match(_.expr($.and([
      $.eq(['$_id''$$customerId'])
    ]))).project({
      _id: false,
      customerTitle: '$title',
      customerPhone: '$phone',
      customerLevel: '$level'
    }).done(),
    as'customers'
  })
  .replaceRoot({
    newRoot: $.mergeObjects([$.arrayElemAt(['$customers'0]), '$$ROOT'])
  })
  .project({
    customers: false
  })
  if (searchWord) {
    queryList = queryList.match(_.or([{
      customerTitle: new RegExp(searchWord, 'i')
    }, {
      customerPhone: new RegExp(searchWord, 'i')
    }]))
  }
  let listRes = await queryList.sort({createTime: -1}).skip(pager.Offset).limit(pager.Limit).end()


  return {
    data: listRes.list,
    pager, // 返回{ data, pager: {Offset, Limit, Total }}这样的数据结构,是为了和云数据库的http读取方式统一
    errMsg: 'collection.aggregate:ok'
  }
最后一次编辑于  2021-06-29
回答关注问题邀请回答
收藏

2 个回答

  • 老张
    老张
    2021-06-29

    https://developers.weixin.qq.com/community/develop/article/doc/0008ea04120a18f6988b86d065b013

    参考一下。

    在云函数里分页,比较麻烦,数据不大的话,不如一次全取。

    2021-06-29
    有用 1
    回复 3
    • yangxuqing
      yangxuqing
      2021-06-29
      张老师好,您这个一次性读取所有文档的方法真的很好用!我先收藏下来待以后方便查阅。只是我现在需要分页读取数据,不知道在查询条件较为复杂的情况下,如何简洁的获取文档总数并当前页数据。望张老师进一步赐教。感谢张老师!
      2021-06-29
      1
      回复
    • 老张
      老张
      2021-06-29回复yangxuqing
      那你的方法已经是最佳了。两次获取是必然的。
      2021-06-29
      1
      回复
    • yangxuqing
      yangxuqing
      2021-06-29
      谢谢张老师,有您这样的肯定,我也就安心了,要不总觉得自己写的代码太丑陋。
      2021-06-29
      回复
  • yangxuqing
    yangxuqing
    2021-06-29
    上面代码中,queryCount和queryList是完全一样的,只不过
    一个是queryCount.count('total').end(),
    一个是queryList.skip(pager.Offset).limit(pager.Limit).end(),
    我尝试过用queryList = queryCount来简化代码,可是发现queryCount.count('total').end()之后,queryList就不能按预期那样读取分页数据了。
    请问像这种分页读取需要同时返回文档总数的,一般是如何写比较简洁的代码的?
    谢谢!
    
    2021-06-29
    有用
    回复 1
    • 坚持梦想
      坚持梦想
      2022-03-02
      只能写两遍。坑的很
      2022-03-02
      回复
登录 后发表内容