如何统计MongoDB文档可查询键总数并获取所有文档中的最大值?
MongoDB文档可查询键统计及最大值获取方案
先看示例文档:
{ "_id": "123", // 1 "parent1": { "child1": "234", // 2 "child2": { "grandchild1": "345", // 3 "grandchild2": { "greatgrand1": "456" // 4 } }, "child3": [ { "grandchild1": "567", // 5 "grandchild2": { "greatgrand1": "678", // 6 "greatgrand2": { "greatgrand1": "789" // 7 } } } ] }, "parent2": [ { "child1": "567", // 8 "child2": { "grandchild1": "678", // 9 "grandchild2": { "greatgrand1": "789" // 10 } } } ] }
这个文档的可查询键总数为10,现在需要统计集合中每个文档的这类键总数,再找出所有文档里的最大值。之前尝试用$objectToArray没找到可行方案,这里直接上可用的聚合管道方案:
解决代码
db.collection.aggregate([ { $addFields: { keyCount: { $function: { body: function(doc) { let count = 0; function traverse(obj) { if (obj && typeof obj === 'object') { if (Array.isArray(obj)) { // 遍历数组中的每个元素 obj.forEach(item => traverse(item)); } else { // 遍历对象的每个键,计数后递归处理值 Object.keys(obj).forEach(key => { count++; traverse(obj[key]); }); } } } traverse(doc); return count; }, args: ["$$ROOT"], lang: "js" } } } }, { $group: { _id: null, maxKeyCount: { $max: "$keyCount" }, // 可选:保留每个文档的ID和对应的键数 docKeyCounts: { $push: { documentId: "$_id", count: "$keyCount" } } } } ])
代码说明
- $addFields阶段:通过
$function自定义JavaScript函数,递归遍历整个文档($$ROOT代表当前文档):- 遇到数组时,遍历数组内的每个元素继续递归;
- 遇到对象时,统计当前键的数量,再递归处理键对应的值;
- 最终返回当前文档的总键数,存入
keyCount字段。
- $group阶段:将所有文档合并为一组,用
$max计算出最大的键数maxKeyCount,同时可以通过$push保留每个文档的ID和对应键数,方便查看单个文档的统计结果。
注意事项
- 该方案要求MongoDB版本在4.4及以上,因为
$function是4.4版本新增的功能; - 如果你的集合有超大规模的嵌套结构或超大数组,JavaScript函数的执行性能会比原生聚合操作稍差,但对于常规业务场景完全够用;
- 示例文档用这个管道处理后,
keyCount会返回10,和预期一致。
内容的提问来源于stack exchange,提问作者John Bench
相关产品推荐
相关产品推荐

