如何在MongoDB中对比同文档字段并筛选异常扫描记录
找出包含「异常扫描」的文档实现方案
需求回顾
需要筛选出满足以下任一条件的文档:
- 至少有一条扫描记录不存在
date字段 - 存在扫描记录的
date早于文档自身date的90天前 - 存在扫描记录的
date晚于文档自身date
场景一:JavaScript 处理现有JSON数据
如果已经拿到JSON格式的数据集,可直接用数组筛选逻辑处理:
// 假设原始数据存储在docs变量中 const abnormalDocs = docs.filter(doc => { const docDate = new Date(doc.date); // 计算文档日期90天前的时间点 const ninetyDaysPrior = new Date(docDate); ninetyDaysPrior.setDate(ninetyDaysPrior.getDate() - 90); // 检查扫描记录是否存在异常 return doc.scans.some(scan => { // 条件1:扫描记录无date字段 if (!scan.date) return true; const scanDate = new Date(scan.date); // 条件2:扫描日期早于文档日期的90天前 if (scanDate < ninetyDaysPrior) return true; // 条件3:扫描日期晚于文档日期 if (scanDate > docDate) return true; return false; }); }); // 输出筛选后的异常文档 console.log(abnormalDocs);
逻辑说明
- 先将文档日期转为
Date对象,计算出90天前的时间节点 - 用
some()遍历扫描记录,只要有一条满足任一异常条件,该文档就会被保留 - 对单条扫描记录依次检查三个条件,满足其一即判定为异常
场景二:MongoDB 数据库直接查询
如果数据存储在MongoDB中,用数据库查询语句可更高效筛选:
db.collection.find({ $or: [ // 条件1:存在扫描记录缺少date字段 { "scans.date": { $exists: false } }, // 条件2:存在扫描日期早于文档日期90天前 { $expr: { $gt: [ { $size: { $filter: { input: "$scans", cond: { $lt: [ { $toDate: "$$this.date" }, { $subtract: [ { $toDate: "$date" }, 90*24*60*60*1000 ] } ] } } } }, 0 ] } }, // 条件3:存在扫描日期晚于文档日期 { $expr: { $gt: [ { $size: { $filter: { input: "$scans", cond: { $gt: [ { $toDate: "$$this.date" }, { $toDate: "$date" } ] } } } }, 0 ] } } ] })
查询逻辑说明
- 用
$or组合三个条件,满足任一即可匹配文档 - 条件1直接通过
$exists: false检查是否有扫描记录缺失date字段 - 条件2和3通过
$filter筛选符合日期条件的扫描记录,再用$size判断是否存在此类记录(数量大于0即满足条件)
内容的提问来源于stack exchange,提问作者muezz
相关产品推荐
相关产品推荐

