Mongoose中使用updateMany将subDocCount设为满足多条件(含ID不在指定数组)的subDocs元素数量
Mongoose中使用updateMany将subDocCount设为满足多条件(含ID不在指定数组)的subDocs元素数量
看起来你已经离正确答案很近啦!问题主要出在两个地方:一是“ID不在指定数组”的条件写法可以更规范,二是你后来发现的ID类型不匹配的坑——这个很容易被忽略,我帮你梳理清楚:
首先,先给你修正后的完整查询代码:
await docs.updateMany( {}, [ { $set: { subDocCount: { $size: { $filter: { input: '$subDocs', as: 'subDoc', cond: { $and: [ { $eq: ['$$subDoc.booleanField', false] }, { $or: [ { $eq: ['$$subDoc.dateField', null] }, { $lt: ['$$subDoc.dateField', startOfToday()] } ] }, // 推荐用$nin,语义更清晰,和$in对应 { $nin: ["$$subDoc.id", excludedIds] } // 也可以用$not+$in,语法是对的,效果一样 // { $not: { $in: ["$$subDoc.id", excludedIds] } } ] } } } } } } ] )
关于“ID不在数组”的写法说明
MongoDB提供了两种方式实现“值不在指定数组中”:
$nin操作符:这是专门做“反向匹配数组”的操作符,用法和$in完全对应,写起来直观易懂,推荐优先用这个。$not + $in组合:你原来的写法语法其实没问题,但$nin更直白,可读性更高,两种写法效果完全一致。
最关键的坑:ID类型匹配
你在编辑里提到的问题才是核心原因——如果excludedIds数组里的ID类型和subDocs.id的存储类型不匹配(比如一个是ObjectId,一个是字符串),哪怕看起来值一样,MongoDB也会判定不匹配,导致条件失效。
解决办法很简单:
- 先确认你的
subDocs.id存的是字符串还是ObjectId; - 如果是ObjectId,就把
excludedIds里的字符串ID转换成ObjectId:const excludedIds = ['你的字符串ID1', '你的字符串ID2'].map(id => mongoose.Types.ObjectId(id)); - 如果是字符串,就确保
excludedIds是纯字符串数组,不要转成ObjectId。
验证小技巧
要是不确定过滤逻辑对不对,可以先写个聚合查询测试一下,看看筛选出的子文档数量是否符合预期:
const testResult = await docs.aggregate([ { $project: { filteredSubDocs: { $filter: { input: '$subDocs', as: 'subDoc', cond: { $and: [ { $eq: ['$$subDoc.booleanField', false] }, { $or: [{ $eq: ['$$subDoc.dateField', null] }, { $lt: ['$$subDoc.dateField', startOfToday()] }] }, { $nin: ["$$subDoc.id", excludedIds] } ] } }, calculatedCount: { $size: '$filteredSubDocs' } } } } ]); console.log(testResult);
先确认calculatedCount是你想要的数值,再把逻辑放到updateMany里执行就稳了。
备注:内容来源于stack exchange,提问作者ThriceGood
相关产品推荐
相关产品推荐

