如何使用Mongoose按字符串类型fecha_proximo_mantenimiento筛选30天内待维护文档
解决方案
你需要匹配fecha_proximo_mantenimiento落在「当前日期」到「当前日期+30天」区间的文档,根据是否可修改字段类型,有两种实现方式:
方案1(推荐):修改字段类型为Date
存为字符串类型的日期在查询、排序时都需要额外转换,性能差且容易出错,建议先调整Schema定义:
// 修改Schema中对应字段配置 fecha_proximo_mantenimiento: { type: Date, // 把String改成Date required: false, trim: true, }
Mongoose会自动将你传入的YYYY-MM-DD格式字符串转换为标准Date类型存储,调整后查询代码如下:
const mongoose = require('mongoose'); // 计算阈值日期:当前时间往后推30天 const now = new Date(); const thresholdDate = new Date(now.getTime() + 30 * 24 * 60 * 60 * 1000); // 注意:contrato是ObjectId类型,需要把字符串转为ObjectId才能匹配 const targetContrato = mongoose.Types.ObjectId('contrato1'); // 如果你给模型起了Dispositivos的别名,直接替换InventarioDispositivos即可 InventarioDispositivos.find( { contrato: targetContrato, fecha_proximo_mantenimiento: { $exists: true, $gte: now, // 排除已经过期的维护日期,不需要的话可以删掉这行 $lte: thresholdDate } }, { _id: 0, 'informacion_equipo.ususario_red': 1, fecha_proximo_mantenimiento: 1 } ).limit(10).then((devices) => { // 返回的fecha_proximo_mantenimiento是Date类型,调用.toISOString().slice(0,10)即可得到YYYY-MM-DD格式字符串 console.log(devices) }).catch(err => { console.log(err) })
方案2:不修改字段类型,使用聚合管道转换日期
如果暂时无法调整存量数据和字段类型,可以用聚合的$dateFromString操作符把字符串转为日期后再过滤:
const mongoose = require('mongoose'); const now = new Date(); const thresholdDate = new Date(now.getTime() + 30 * 24 * 60 * 60 * 1000); const targetContrato = mongoose.Types.ObjectId('contrato1'); InventarioDispositivos.aggregate([ // 先过滤符合条件的基础数据,缩小范围 { $match: { contrato: targetContrato, fecha_proximo_mantenimiento: { $exists: true } } }, // 把字符串日期转为Date类型,存为临时字段 { $addFields: { mantenimientoDate: { $dateFromString: { dateString: '$fecha_proximo_mantenimiento', // 如果有时区需求可以加上时区配置,比如中国时区是 timezone: "Asia/Shanghai" } } } }, // 过滤符合30天内条件的文档 { $match: { mantenimientoDate: { $gte: now, // 不需要排除过期的话可以删掉这行 $lte: thresholdDate } } }, // 保留需要返回的字段 { $project: { _id: 0, 'informacion_equipo.ususario_red': 1, fecha_proximo_mantenimiento: 1 } }, { $limit: 10 } ]).then((devices) => { console.log(devices) }).catch(err => { console.log(err) })
注意事项
- 如果你的
fecha_proximo_mantenimiento格式不是标准YYYY-MM-DD,需要在$dateFromString中指定format参数 - 如果你需要包含已经过期的维护日期,删除上述代码中的
$gte: now条件即可
内容的提问来源于stack exchange,提问作者Diego Sanchez
相关产品推荐
相关产品推荐

