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

如何基于MongoDB中query字段频次获取指定时段的文档排名?

MongoDB按指定时间范围统计Query频次并生成排名

可以通过MongoDB的聚合管道实现这个需求,以下是具体的实现方案:

核心聚合逻辑

通过聚合管道的多阶段组合,完成过滤、统计、排序、排名的完整流程:

  1. 过滤时间范围:用$match筛选出指定时间区间内的文档
  2. 分组统计频次:用$group按目标字段(这里是query)分组,计算每个值的出现次数
  3. 按频次排序:用$sort根据统计出的频次降序排列结果
  4. 生成排名:用$setWindowFields为每个分组添加连续的排名字段
  5. 整理输出格式:用$project调整输出字段结构,匹配预期的返回格式

完整聚合代码示例

假设你的集合名为queries,对应的聚合查询如下:

const startUnix = 1660610670;
const endUnix = 1660610682;

db.queries.aggregate([
  // 1. 匹配指定时间范围的文档
  {
    $match: {
      createdAt: { $gte: startUnix, $lt: endUnix }
    }
  },
  // 2. 分组统计每个query的频次
  {
    $group: {
      _id: "$query",
      frequency: { $sum: 1 }
    }
  },
  // 3. 按频次降序排序
  {
    $sort: { frequency: -1 }
  },
  // 4. 计算排名(按频次降序,相同频次会获得相同排名)
  {
    $setWindowFields: {
      sortBy: { frequency: -1 },
      output: {
        rank: { $rank: {} }
      }
    }
  },
  // 5. 调整输出字段,把_id改为query
  {
    $project: {
      _id: 0,
      rank: 1,
      query: "$_id",
      frequency: 1
    }
  }
])

封装成指定调用方式(以Mongoose为例)

如果使用Mongoose操作,可以给Queries模型添加静态方法getRank,适配你预期的调用格式:

Queries.schema.statics.getRank = async function(params) {
  const { key, createdAt } = params;
  return this.aggregate([
    { $match: { createdAt } },
    { $group: { _id: `$${key}`, frequency: { $sum: 1 } } },
    { $sort: { frequency: -1 } },
    {
      $setWindowFields: {
        sortBy: { frequency: -1 },
        output: { rank: { $rank: {} } }
      }
    },
    {
      $project: {
        _id: 0,
        rank: 1,
        [key]: "$_id",
        frequency: 1
      }
    }
  ]);
};

// 调用示例
const result = await Queries.getRank({
  key: 'query',
  createdAt: { $gte: startUnix, $lt: endUnix }
});

注意事项

  • 如果需要处理并列排名(比如两个query频次相同),可以用$denseRank替代$rank,$denseRank不会跳过并列后的排名数字
  • 建议给createdAt字段创建索引,避免数据量较大时时间范围匹配的性能问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 11:10:42