如何在MongoDB中过滤含_flag后缀的多键字段?
筛选包含任意以
_flag后缀且值为false的文档 嘿,刚好处理过类似的动态键筛选需求,给你两个靠谱的方案,根据你的文档结构灵活选择:
方案1:通用型(支持任意嵌套层级,MongoDB 4.4+可用)
如果你的文档里_flag键可能出现在任意层级(比如子文档、数组里的对象),用这个聚合管道+自定义函数的方案最稳妥,它会递归遍历整个文档的所有键:
db.collection.aggregate([ { $match: { $expr: { $function: { body: function(doc) { // 递归检查所有键值对的辅助函数 function checkFlag(obj) { if (obj === null || typeof obj !== 'object') return false; // 处理数组:遍历每个元素检查 if (Array.isArray(obj)) { return obj.some(item => checkFlag(item)); } // 处理对象:遍历所有键 for (const key in obj) { // 检查当前键是否以_flag结尾且值为false if (key.endsWith('_flag') && obj[key] === false) { return true; } // 递归检查子文档 if (typeof obj[key] === 'object' && obj[key] !== null) { if (checkFlag(obj[key])) return true; } } return false; } return checkFlag(doc); }, args: ["$$ROOT"], lang: "js" } } } } ])
方案2:针对固定结构的简化版
如果你的_flag键固定出现在details.form数组的对象里,不用递归这么麻烦,直接用数组匹配就能搞定:
db.collection.find({ "details.form": { $elemMatch: { $expr: { $anyElementTrue: { $map: { input: { $objectToArray: "$$CURRENT" }, as: "kv", in: { $and: [ { $regexMatch: { input: "$$kv.k", regex: /_flag$/ } }, { $eq: ["$$kv.v", false] } ] } } } } } } })
关键操作符说明
$objectToArray:把对象转成[{k: "键名", v: "值"}]的数组,方便遍历动态生成的键$regexMatch:用来匹配键名是否以_flag结尾$function:自定义JS函数,帮你递归遍历所有层级的文档内容,不怕嵌套深$elemMatch:确保数组里至少有一个元素符合我们的筛选条件
用这两个方案测试你给的示例文档,都会成功匹配到,因为它的details.form里确实有两个_flag键值为false的对象~
内容的提问来源于stack exchange,提问作者khiru
相关产品推荐
相关产品推荐

