如何在MongoDB中查询文档不同层级下的同名字段值
MongoDB不限嵌套层级查询指定字段所有值的实现方案
完全可以实现该需求,你可以通过MongoDB聚合管道结合自定义递归函数的方式,提取任意嵌套层级下指定字段的所有值,不需要提前知道字段的嵌套位置。
针对你给出的文档结构,参考聚合查询语句如下:
db.collection.aggregate([ { $addFields: { allIps: { $function: { body: function(doc) { const ips = []; // 递归遍历所有层级的对象和数组 const extractIp = (target) => { if (Array.isArray(target)) { target.forEach(item => extractIp(item)); return; } if (typeof target === 'object' && target !== null) { Object.keys(target).forEach(key => { if (key === 'ip') { ips.push(target[key]); } else { extractIp(target[key]); } }) } } extractIp(doc); return ips; }, args: ["$$ROOT"], lang: "js" } } } }, // 以下两个阶段为可选,用于将集合内所有文档的ip合并为全局列表 { $unwind: "$allIps" }, // 若不需要去重,将$addToSet改为$push即可 { $group: { _id: null, globalIps: { $addToSet: "$allIps" } } } ])
方案说明
- 自定义函数会递归遍历当前完整文档(
$$ROOT代表当前文档的全部内容)的所有层级,包括嵌套对象、嵌套数组内部的字段 - 只要匹配到键名为
ip的字段,就会将对应值存入结果数组,不受嵌套位置和层级限制 - 如果仅需要每个文档自身包含的所有ip列表,删除聚合管道最后的
$unwind和$group阶段即可
注意事项
- 该方案要求MongoDB版本 >= 4.4,仅该版本及以上支持
$function运算符 - 若使用的MongoDB版本更低,可以在应用服务层读取文档后,复用上面的
extractIp递归逻辑完成字段提取 - 若你明确知道所有
ip字段可能出现的嵌套路径,也可以通过$project+$concatArrays手动合并所有路径的ip值,该方案查询性能更高,但扩展性差,新增嵌套路径时需要修改查询语句
内容的提问来源于stack exchange,提问作者RaamEE
相关产品推荐
相关产品推荐

