MongoDB基于指定键关联两个集合且不生成嵌套结构的实现方案
解决MongoDB集合关联后扁平化结果的问题
你现在用$lookup得到的是嵌套数组结构,要生成没有嵌套的扁平文档并写入新集合,只需要在聚合管道里添加两步处理:展开数组、合并字段到顶层。
修改后的聚合代码
db.twitter.aggregate([ // 第一步:按name关联两个集合,得到嵌套数组 { "$lookup": { "from": "wikipedia", "localField": "name", "foreignField": "name", "as": "linked_collections" } }, // 第二步:展开嵌套的数组(如果一个name对应多条维基记录,会生成多个文档,类似SQL的inner join) { "$unwind": "$linked_collections" }, // 第三步:合并原文档和维基记录的字段到顶层,同时清理不需要的_id { "$replaceRoot": { "newRoot": { "$mergeObjects": [ // 保留twitter集合需要的字段,移除原_id { "_id": "$$REMOVE", "name": "$name", "username_twitter": "$username_twitter", "user_id_twitter": "$user_id_twitter", "text_twitter": "$text_twitter" }, // 提取维基集合需要的字段,移除维基的_id { "_id": "$$REMOVE", "page_wikipedia": "$linked_collections.page_wikipedia", "text_wikipedia": "$linked_collections.text_wikipedia" } ] } } }, // 第四步:将结果写入新集合twitter_wikipedia { "$out": "twitter_wikipedia" } ])
代码说明
$unwind:把linked_collections数组拆分成单个文档,彻底去掉数组嵌套。如果你的数据里存在一个name对应多条维基记录的情况,这一步会生成多条关联后的文档,和SQL的INNER JOIN效果一致。如果要实现LEFT JOIN(保留没有匹配维基记录的twitter文档),可以改成:{ "$unwind": { "path": "$linked_collections", "preserveNullAndEmptyArrays": true } }$replaceRoot+$mergeObjects:把原twitter文档的字段和维基记录里的目标字段合并成一个顶层文档,用$$REMOVE关键字移除两个集合的_id(如果需要保留某个_id,直接删除对应的"_id": "$$REMOVE"行即可)。$out:将最终的扁平文档写入指定的新集合。
验证结果
运行上述聚合后,执行:
db.twitter_wikipedia.find_one({})
就能得到你期望的扁平结构:
{'name': 'Nike', 'username_twitter': 'nikestore', 'user_id_twitter': 17351972, 'text_twitter': '@sillspb Hey, Paul. What error message are you seeing on your end?', 'page_wikipedia': 'Nike,_Inc.', 'text_wikipedia': 'Nike, Inc. ( or ) is an American multinational corporation that is engaged in the design, development, manufacturing, and worldwide marketing and sales of footwear, apparel, equipment, accessories, and services.'}
内容的提问来源于stack exchange,提问作者SkuPak
相关产品推荐
相关产品推荐

