MongoDB中用MapReduce合并DEVICE与READING集合生成全字段新集合遇空值问题
解决MongoDB MapReduce合并集合时出现空值的问题
嘿,我懂你现在的烦恼——想用MapReduce合并DEVICE和READING集合,结果新集合里一堆空值,没留住两个原集合的所有字段对吧?别慌,咱们一步步把这个问题捋顺~
问题根源分析
你遇到空值的核心原因大概率是这两点:
- 你的Map函数只处理了公共关联字段(比如
deviceId),没完整输出每个集合的所有字段 - Reduce阶段没区分DEVICE和READING文档的类型,合并时丢了非公共字段,导致不存在的字段被留空
另外插一句:MongoDB从3.2版本开始,**聚合框架的$lookup**其实比MapReduce更适合做集合关联合并,不仅性能更高,写法也直观得多。不过咱们先解决你用MapReduce的需求,再给你推荐更优方案~
正确的MapReduce实现(保留所有字段)
1. 编写Map函数
这个函数要做的是:标记每个文档的类型(DEVICE/READING),并把完整文档作为值输出,用关联键(比如deviceId)作为emit的key:
var mapFunc = function() { // 根据独有的字段判断文档类型(比如READING有readingId,DEVICE没有) const docType = this.readingId ? 'READING' : 'DEVICE'; // 用deviceId作为关联键,把完整文档和类型一起输出 emit(this.deviceId, { [docType]: this, type: docType }); };
2. 编写Reduce函数
这个函数要把同一个deviceId下的DEVICE和所有READING文档合并,完整保留所有字段:
var reduceFunc = function(key, values) { // 初始化结果:一个DEVICE对应多个READING的场景 const mergedResult = { device: null, readings: [] }; values.forEach(item => { // 合并DEVICE文档(每个deviceId对应一个DEVICE) if (item.type === 'DEVICE') { mergedResult.device = item.DEVICE; } // 收集所有对应的READING文档 if (item.type === 'READING') { mergedResult.readings.push(item.READING); } }); // 如果需要把DEVICE的字段和READING数组平级(不嵌套),可以再加这一步: const finalDoc = { ...mergedResult.device }; finalDoc.readings = mergedResult.readings; return finalDoc; };
3. 执行MapReduce
注意:MapReduce默认只能处理单个集合,所以要同时处理DEVICE和READING,咱们分两次执行并合并结果:
// 第一次处理DEVICE集合,直接生成目标集合 db.DEVICE.mapReduce( mapFunc, reduceFunc, { out: { replace: "map_reduce_example" } } ); // 第二次处理READING集合,用merge模式合并到目标集合 db.READING.mapReduce( mapFunc, reduceFunc, { out: { merge: "map_reduce_example" } } );
更优方案:用聚合框架$lookup实现
MapReduce现在已经逐渐被聚合框架替代了,用$lookup来关联集合更简单高效,还能完美保留所有字段:
db.DEVICE.aggregate([ // 关联READING集合,匹配deviceId字段 { $lookup: { from: "READING", localField: "deviceId", foreignField: "deviceId", as: "related_readings" } }, // 将结果输出到目标集合 { $out: "map_reduce_example" } ]);
这样生成的集合里,每个文档会包含DEVICE的所有原始字段,同时related_readings字段是对应DEVICE的所有READING文档数组——完全没有空值,除非某个DEVICE没有对应的READING,此时related_readings是空数组(这是合理的,不是无效空值)。
内容的提问来源于stack exchange,提问作者Yashwin Munsadwala
相关产品推荐
相关产品推荐

