javascript 如何仅对基于某些字段唯一文档$bucket

bvjxkvbb  于 2023-01-04  发布在  Java
关注(0)|答案(1)|浏览(117)

我使用的是Mongo聚合框架,假设我有这样的集合结构

{
  {
    _id: ObjectId(123)
    name: john,
    sessionDuration: 29
  },
  {
    _id: ObjectId(456)
    name: moore,
    sessionDuration: 45
  },
  {
    _id: ObjectId(789)
    name: john,
    sessionDuration: 25
  },
  {
    _id: ObjectId(910)
    name: john,
    sessionDuration: 45
  },
  etc...
}

具有相同name的用户是使用不同会话的用户,如下例所示:John正在使用三台设备的服务,持续时间为3 sessions2小于30(29,25)1小于50(45)
我想对边界[0,30,50]执行bucket查询,但在该范围内,它必须仅对名称唯一的用户计数,持续时间少于30或50的同名用户计数不得超过一个,这意味着结果应如下所示

{
  time: Unique_Name_Users_Only_Lies_In_This_Boundary,
  ‘30’: 1,
  ‘50’: 2,
}

因此,John有2个会话少于30个持续时间,因此我们只需要这两个会话中的1个。

**我尝试了什么:**我首先用唯一的名称对所有文档进行分组,然后应用bucket。但是这种方法也会跳过会话持续时间为45的john。

如何仅获取$bucket boundary特定持续时间内的唯一名称文档计数?

svmlkihl

svmlkihl1#

一种选择是将$bucket$addToSet一起使用,然后将$group$arrayToObject一起使用,以获得您的格式:

db.collection.aggregate([
  {$bucket: {
      groupBy: "$sessionDuration",
      boundaries: [0, 30, 50],
      default: "Other",
      output: {res: {$addToSet: "$name"}}
  }},
  {$group: {
      _id: 0,
      res: {$push: {k: {$toString: "$_id"},  v: {$size: "$res"}}}
  }},
  {$replaceRoot: {newRoot: {$arrayToObject: "$res"}}}
])

了解它在playground example上的工作原理

  • 注意,bucket的_id是它的下边界,如果您确实需要,可以对其进行操作,但我不推荐这样做

相关问题