MongoDB 3.4等旧版本中$expr的替代实现方案是什么?
适配MongoDB 3.4的查询实现方案
MongoDB 3.4不支持$expr语法,你当前的场景有两种可落地的替代方案,优先推荐性能更好的日期范围查询方案:
方案1:日期范围匹配(优先推荐)
通过计算目标月份的起止时间做范围查询,完全不需要使用表达式运算,兼容MongoDB 3.2及以上版本,且可以利用closingDate的索引提升查询效率,实现代码如下:
// 计算目标月份的第一天零点 const startOfMonth = new Date(date.getFullYear(), date.getMonth(), 1); // 计算目标月份下一个月的第一天零点,作为范围右开边界 const startOfNextMonth = new Date(date.getFullYear(), date.getMonth() + 1, 1); const orders = await OrderModel.find({ entityId: entityId, closingDate: { $ne: null, $gte: startOfMonth, $lt: startOfNextMonth } }).lean();
该方案的查询逻辑和你原$expr实现的效果完全一致,性能远优于表达式查询的实现。
方案2:聚合管道实现(通用表达式场景替代)
如果你有其他必须要做字段运算匹配的场景,可通过聚合管道的投影+匹配逻辑实现$expr的等价效果,3.4版本原生支持聚合的相关运算符:
const orders = await OrderModel.aggregate([ // 第一层匹配先过滤掉不符合基础条件的文档,减少后续运算量 { $match: { entityId: entityId, closingDate: { $ne: null } } }, // 投影出需要做运算匹配的年、月字段 { $project: { root: "$$ROOT", closingYear: { $year: "$closingDate" }, closingMonth: { $month: "$closingDate" } } }, // 匹配目标年月 { $match: { closingYear: date.getFullYear(), closingMonth: date.getMonth() + 1 } }, // 还原为原始文档结构 { $replaceRoot: { newRoot: "$root" } } ]);
该方案的缺点是无法利用索引做年、月维度的过滤,数据量较大时性能低于方案1,仅建议用于无法用范围查询替代的表达式匹配场景。
内容的提问来源于stack exchange,提问作者FlushBG
相关产品推荐
相关产品推荐

