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

如何用MongoDB聚合查询筛选索引可被5整除的记录?

需求:MongoDB聚合查询筛选指定索引的记录

场景说明

我的usages集合数据结构如下(实际有40000条记录,以下为示例):

{ _id: AUTOGENERATED_MONGO_OBJECT_ID, timeStamp: 1675122960, usage: null, limit: 2.7 },
{ _id: AUTOGENERATED_MONGO_OBJECT_ID, timeStamp: 1675123020, usage: 2.74, limit: 2.7 },
{ _id: AUTOGENERATED_MONGO_OBJECT_ID, timeStamp: 1675123080, usage: 2.62, limit: 2.7 },
{ _id: AUTOGENERATED_MONGO_OBJECT_ID, timeStamp: 1675123140, usage: 4.32, limit: 2.7 },
{ _id: AUTOGENERATED_MONGO_OBJECT_ID, timeStamp: 1675123200, usage: null, limit: 2.7 },
{ _id: AUTOGENERATED_MONGO_OBJECT_ID, timeStamp: 1675123260, usage: 5.38, limit: 2.7 },
{ _id: AUTOGENERATED_MONGO_OBJECT_ID, timeStamp: 1675123320, usage: 5.08, limit: 2.7 },
{ _id: AUTOGENERATED_MONGO_OBJECT_ID, timeStamp: 1675123380, usage: 1.02, limit: 2.7 },
{ _id: AUTOGENERATED_MONGO_OBJECT_ID, timeStamp: 1675123440, usage: 2.35, limit: 2.7 },

原本我用Mongoose查询获取最后60条数据:

const count = await Usage.count()
Usage.find({}).sort({ timeStamp: 1 }).skip(count - 60);

现在需要从这60条数据里筛选出索引可被5整除的12条记录(用于前端折线图展示)。当前我是先查所有60条再在客户端过滤:

const count = await Usage.count();
const data = await Usage
    .find({})
    .sort({ timeStamp: 1 })
    .skip(count - start)
    .exec();
const requiredData = data.filter((item, index) => index % 5 === 0);
console.log(requiredData);

但客户端过滤速度太慢,希望用MongoDB聚合查询在数据库层面完成筛选。

解决方案

可以通过聚合管道的$sort、$limit、$setWindowFields等操作,在数据库层面完成排序、截取目标数据、添加索引、筛选的全流程,具体实现如下:

Mongoose聚合代码

const requiredData = await Usage.aggregate([
  // 1. 倒序排序,直接取最新的60条数据
  { $sort: { timeStamp: -1 } },
  { $limit: 60 },
  // 2. 转回升序,和原查询的顺序保持一致
  { $sort: { timeStamp: 1 } },
  // 3. 为每条记录添加从1开始的序号
  {
    $setWindowFields: {
      sortBy: { timeStamp: 1 },
      output: {
        index: { $documentNumber: {} }
      }
    }
  },
  // 4. 将序号转为从0开始,和客户端过滤的索引逻辑对齐
  { $addFields: { index: { $subtract: ["$index", 1] } } },
  // 5. 筛选索引能被5整除的记录
  { $match: { index: { $mod: [5, 0] } } },
  // 6. 移除临时添加的index字段,返回原数据结构
  { $project: { index: 0 } }
]);

console.log(requiredData);

代码说明

  1. $sort + $limit:先倒序取最新60条,再转回升序,避免了先查总条数再跳过的两次查询,性能更优且不会出现数据不一致的问题。
  2. $setWindowFields + $documentNumber:为每条记录生成自增序号,作为筛选的索引依据。
  3. $addFields:把从1开始的序号转为0开始,和客户端过滤的索引逻辑完全匹配。
  4. $match:用$mod操作符筛选索引能被5整除的记录,直接在数据库完成过滤。
  5. $project:移除临时添加的index字段,返回和原查询结构一致的数据。

性能优化提示

  • 确保timeStamp字段创建了升序索引:await Usage.createIndex({ timeStamp: 1 }),这样排序操作会走索引,避免全表扫描,大幅提升查询速度。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 11:57:49