MongoDB字符串字段查询能否同时使用$regex与$gte/$lte操作符
报错原因
- 类型不匹配:
$gte、$lte是值比较操作符,仅支持传入字符串、数值、Date类型的对比值,你向操作符内传入了{$regex: ...}的正则对象,和Schema中Trandate定义的String类型不匹配,触发类型转换错误。 - 重复键覆盖:JS对象不允许存在同名键,你在查询条件中写了两次Trandate,后定义的
{$lte: ...}会覆盖之前的{$gte: ...},导致查询条件缺失。 - 格式逻辑错误:你用
hi-IN区域的toLocaleDateString输出的是日/月/年格式,和库中存储的月/日/年格式不匹配,即使没有类型错误也无法匹配到正确数据;且M/D/YYYY格式的字符串直接做字典序大小比较会出现乱序问题(如10/1/2021<2/1/2021),无法得到正确的区间结果。
正确实现方案
方案1:修改存储类型(推荐)
将Trandate字段从字符串类型改为MongoDB原生Date类型,既可以避免格式转换问题,查询性能也远高于字符串匹配:
// 结束日期设置为当天最后一毫秒,避免遗漏结束日期当天的记录 const start = new Date(FromDate); const end = new Date(ToDate); end.setHours(23, 59, 59, 999); const chooseWinner = await Transaction.find( { ContCode: CountryCode, CurrCode: CurrCode, CorrOrgCode: CorrorgCode, ServCode: ServCode, BranchCode: BranchCode, Trandate: {$gte: start, $lte: end} }, "CustomerCode ReferenceNo Trandate " );
方案2:不改现有存储结构
如果无法修改历史存储格式,使用聚合管道将字符串转成Date类型后再做区间过滤:
const chooseWinner = await Transaction.aggregate([ // 先过滤非日期条件,缩小扫描范围 {$match: { ContCode: CountryCode, CurrCode: CurrCode, CorrOrgCode: CorrorgCode, ServCode: ServCode, BranchCode: BranchCode }}, // 把字符串格式的Trandate转成Date类型 {$addFields: { TrandateDate: { $dateFromString: { dateString: "$Trandate", format: "%m/%d/%Y %H:%M:%S %p" } } }}, // 日期区间过滤 {$match: { TrandateDate: { $gte: new Date(FromDate), $lte: new Date(new Date(ToDate).setHours(23,59,59,999)) } }}, // 输出指定字段 {$project: { CustomerCode: 1, ReferenceNo: 1, Trandate: 1, _id: 0 }} ])
内容的提问来源于stack exchange,提问作者Soha
相关产品推荐
相关产品推荐

