MongoDB Bson与Java:如何将父文档字段添加至子文档并返回?
问题分析与解决
核心问题
你的代码里replaceWith("$children")这一步会完全替换当前文档为子文档的内容,之前通过addFields添加到根级的parent_desc会被直接丢弃,所以后续投影阶段根本找不到$parent_desc字段,自然无法填充。
另外,原代码里的addFieldsStage写法冗余:$ROOT.parent_desc等价于直接写$parent_desc,不过这不是导致字段丢失的核心原因。
修正方案
下面提供两种可行的修改方式,都不需要硬编码parent_desc的值,直接从父文档获取:
方案一:展开子文档后合并父字段
调整步骤顺序,先展开子文档,再把父文档的parent_desc合并到子文档对象中,最后替换文档:
private List<Bson> createQuery() { List<Bson> pipeline = new ArrayList<>(); // 关联子文档集合,匹配parent_id Bson lookupStage = Aggregates.lookup( "myCollection", "parent_id", "parent_id", "children" ); pipeline.add(lookupStage); // 展开子文档数组 pipeline.add(Aggregates.unwind("$children")); // 将父文档的parent_desc注入到子文档对象中 Bson mergeParentFieldStage = Aggregates.addFields( new Field<>("children.parent_desc", "$parent_desc") ); pipeline.add(mergeParentFieldStage); // 替换为已注入父字段的子文档 pipeline.add(Aggregates.replaceWith("$children")); pipeline.add(projectFields()); return pipeline; }
方案二:关联后直接处理子文档数组
在关联得到子文档数组后,用$map和$mergeObjects直接给每个子元素添加parent_desc,再展开替换:
private List<Bson> createQuery() { List<Bson> pipeline = new ArrayList<>(); // 关联子文档集合 Bson lookupStage = Aggregates.lookup( "myCollection", "parent_id", "parent_id", "children" ); pipeline.add(lookupStage); // 遍历子文档数组,给每个子文档合并父文档的parent_desc字段 Bson injectParentFieldStage = Aggregates.addFields(new Document( "children", new Document("$map", new Document() .append("input", "$children") .append("as", "child") .append("in", new Document("$mergeObjects", Arrays.asList( "$$child", new Document("parent_desc", "$parent_desc") ))) ) )); pipeline.add(injectParentFieldStage); pipeline.add(Aggregates.unwind("$children")); pipeline.add(Aggregates.replaceWith("$children")); pipeline.add(projectFields()); return pipeline; }
两种方案都能保证子文档携带父文档的parent_desc字段,后续投影阶段就能正常读取该字段进行映射。
内容的提问来源于stack exchange,提问作者java12399900
相关产品推荐
相关产品推荐

