C#使用MongoDB驱动执行Aggregate Lookup查询触发类型转换异常
MongoDB聚合关联查询接口报类型转换异常排查
复现场景
基于MongoDB C#驱动开发双集合关联查询接口时,编写的聚合查询代码如下:
var res = _postCollection.Aggregate() .Lookup("_commentCollection", "Comments", "_id", "result") .ToList(); return OK(res);
通过Postman调用该接口时,抛出如下类型转换异常:
System.InvalidCastException: Unable to cast object of type 'MongoDB.Bson.BsonObjectId' to type 'MongoDB.Bson.BsonBoolean'. at get_AsBoolean(Object ) at System.Text.Json.JsonPropertyInfoNotNullable`4.OnWrite(WriteStackFrame& current, Utf8JsonWriter writer) ...............
报错核心原因
- 调用
Aggregate()方法时未指定泛型输出类型,驱动默认以无类型的BsonDocument形式承载查询结果 - ASP.NET Core内置的
System.Text.Json序列化器会遍历BsonDocument的所有公开属性,错误将BsonValue基类上的IsBoolean/IsObjectId等元数据标识属性识别为需要序列化的业务字段;当序列化器访问IsBoolean属性时,内部会直接读取Bson值的AsBoolean属性做类型转换,若当前Bson值为BsonObjectId类型,就会触发类型转换失败 - 原Lookup查询的参数映射逻辑本身不存在顺序错误,但由于没有绑定明确的输出结构,查询返回的字段无法匹配业务模型,也无法实现预期的接口返回效果
可落地的修正方案
- 为聚合查询绑定明确的强类型输出DTO,从根源上避免无类型BsonDocument的序列化问题。修正后的代码示例:
// 定义与查询输出结构匹配的DTO public class PostWithCommentsDto { public ObjectId Id { get; set; } public string Title { get; set; } // 按需补充其他Post模型需要返回的属性 public List<Comment> Comments { get; set; } } // 调整聚合查询逻辑,指定强类型输出 var res = _postCollection.Aggregate<Post, PostWithCommentsDto>() .Lookup( foreignCollectionName: "_commentCollection", localField: post => post.Comments, foreignField: comment => comment.Id, result: dto => dto.Comments ) .ToList(); return OK(res); - 如果必须保留无类型查询逻辑,可在项目的
System.Text.Json配置中添加专门的BsonValue序列化转换器,适配Bson类型的序列化规则,避免默认序列化器错误读取Bson内部的元数据属性。
内容的提问来源于stack exchange,提问作者Hridoy_089
相关产品推荐
相关产品推荐

