MongoDB左连接查询:如何保留左集合全部文档(含无匹配场景)
实现MongoDB左连接保留所有Instance文档的解决方案
问题原因
你当前的代码里,Unwind方法默认会丢弃数组为空或字段为Null的文档——这就是为什么没有匹配Template/Sample的Instance会从结果中消失的原因。MongoDB的Lookup本身是左外连接,会保留左集合的所有数据,但后续的Unwind把空匹配的文档过滤掉了。
修复步骤
1. 给Unwind添加保留空文档的参数
对每个Unwind调用,加上preserveNullAndEmptyArrays: true,这样即使Lookup返回空数组或者Null,对应的Instance也不会被过滤。
2. 可选:处理空匹配的默认值
如果你的C#实体类不允许Template或Samples为Null,可以用AddFields配合$ifNull操作符,把Null值替换成默认的空对象,避免反序列化时出现Null引用错误。
完整代码
var data = _mongoDatabase.GetCollection<Instance>("Instance").Aggregate() // 左连Templates:用Instance的TemplateId匹配Template的TId,结果存到Template数组 .Lookup("Templates", "TemplateId", "TId", @as: "Template") // 展开Template数组,保留空/Null的情况 .Unwind(new StringFieldDefinition<Instance>("Template"), preserveNullAndEmptyArrays: true) // 左连Samples:用Instance的TemplateId匹配Sample的TemplateId,结果存到Template.Samples数组 .Lookup("Sample", "TemplateId", "TemplateId", @as: "Template.Samples") // 展开Samples数组,保留空/Null的情况 .Unwind(new StringFieldDefinition<Instance>("Template.Samples"), preserveNullAndEmptyArrays: true) // 把Null的Template/Samples替换成默认对象(可选,根据你的实体类需求调整) .AddFields(new BsonDocument { { "Template", new BsonDocument("$ifNull", new BsonArray { "$Template", new BsonDocument { { "TId", 0 }, { "Name", "" }, { "Samples", new BsonArray() } } }) }, { "Template.Samples", new BsonDocument("$ifNull", new BsonArray { "$Template.Samples", new BsonDocument { { "SId", 0 }, { "TemplateId", 0 }, { "SampleData", 0 }, { "Name", "" } } }) } }) .As<Instance>() .ToList();
关键细节
Lookup本身就是左外连接,会自动保留所有Instance文档,右集合无匹配时返回空数组。- 必须给
Unwind加preserveNullAndEmptyArrays: true,否则空数组/Null会导致主文档被过滤,这是核心修复点。 - 如果你的实体类允许
Template或Samples为Null,可以去掉AddFields那一段,直接用前面的Lookup+Unwind代码即可。
内容的提问来源于stack exchange,提问作者Rushi Sharma
相关产品推荐
相关产品推荐

