You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MongoDB聚合查询中如何结合分页实现基于review_count的排名?

为MongoDB聚合查询的分页结果添加基于review_count的item_rank

现有查询与数据结构

当前已实现排序和分页的MongoDB聚合查询如下:

db.user_stats.aggregate([
  {"$match":{"company_id":5}},
  {"$group":{
    "_id":"$item_id",
    "review_count":{"$sum":"$review_count"},
    "avg_rating":{"$avg":"$avg_rating"},
    "item_id":{"$first":"$item_id"},
    "item_type":{"$first":"$item_type"},
    "company_id":{"$first":"$company_id"},
    "object_id":{"$first":"$_id"}
  }},
  {"$skip":0},
  {"$limit":20},
  {"$sort":{"review_count":1}}
])

数据存储结构示例:

{
  "_id": {"$oid": "639c7103e687877baf0b2f57"},
  "review_count": 1,
  "avg_rating": 4,
  "item_id": 2,
  "item_type": "user",
  "company_id": 5,
  "created_date": "2022-12-16 11:47:01"
},
{
  "_id": {"$oid": "639c7103e687877baf0b2f57"},
  "review_count": 10,
  "avg_rating": 4,
  "item_id": 2,
  "item_type": "user",
  "company_id": 5,
  "created_date": "2022-12-16 11:47:01"
}

需求说明

需要为分页后的每条记录添加基于review_count排序的item_rank(支持并列排名,即相同review_count的记录排名一致),同时输出包含总条数、当前页码、总页数的结构化结果,格式示例:

"items": {
  "totalCount": 2,
  "current": 1,
  "totalPages": 1,
  "data": [
    {
      "id": "639c7103e687877baf0b2f57",
      "item_id": 2,
      "item_type": "team",
      "item_title": "Team1",
      "item_rank": 2
    },
    {
      "id": "639c7103e687877baf0b2f51",
      "item_id": 23,
      "item_type": "team",
      "item_rank": 2
    }
  ]
}

解决方案

调整聚合阶段顺序,通过$setWindowFields计算排名,并用$facet同时处理统计与分页数据:

db.user_stats.aggregate([
  // 过滤目标公司数据
  {"$match":{"company_id":5}},
  // 按item_id分组聚合
  {"$group":{
    "_id":"$item_id",
    "review_count":{"$sum":"$review_count"},
    "avg_rating":{"$avg":"$avg_rating"},
    "item_id":{"$first":"$item_id"},
    "item_type":{"$first":"$item_type"},
    "company_id":{"$first":"$company_id"},
    "object_id":{"$first":"$_id"}
  }},
  // 先排序,保证分页逻辑正确
  {"$sort":{"review_count":1}},
  // 同时处理统计和分页数据
  {"$facet":{
    "totalCount": [{"$count": "value"}],
    "data": [
      {"$skip":0},
      {"$limit":20},
      // 计算并列排名(相同review_count排名一致)
      {"$setWindowFields":{
        "partitionBy": null,
        "sortBy": {"review_count":1},
        "output": {
          "item_rank": {"$denseRank": {}}
          // 若需跳跃式排名,替换为"$rank": {}
        }
      }},
      // 调整字段匹配期望格式
      {"$project":{
        "id": "$object_id",
        "item_id": 1,
        "item_type": 1,
        "review_count": 1,
        "avg_rating": 1,
        "item_rank": 1,
        "_id": 0
      }}
    ]
  }},
  // 整理输出结构,计算总页数
  {"$project":{
    "totalCount": {"$arrayElemAt": ["$totalCount.value", 0]},
    "current": 1, // 可根据skip值动态计算,如skip=20则current=2
    "totalPages": {"$ceil": {"$divide": [{"$arrayElemAt": ["$totalCount.value", 0]}, 20]}},
    "data": "$data"
  }},
  // 包裹到items字段
  {"$project":{
    "items": "$$ROOT"
  }}
])

关键说明

  1. 排序阶段前置:将$sort移至$skip/$limit之前,确保分页基于排序后的完整数据集,避免逻辑错误。
  2. 排名计算:$denseRank实现连续并列排名,相同review_count的记录排名一致;若需跳跃式排名(如1,2,2,4),改用$rank。
  3. $facet优化查询:一次聚合同时完成总数统计和分页数据处理,减少数据库交互次数。
  4. 字段适配:通过$project调整字段名与结构,完全匹配需求输出格式。

内容的提问来源于stack exchange,提问作者Jitender Thakur

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 04:15:49