MongoDB .NET Driver:使用ElemMatch筛选时间区间遇序列化报错求解
解决MongoDB ElemMatch筛选时间区间时的序列化错误
问题根源
你遇到的Unable to cast object of type 'MongoDB.Bson.Serialization.Serializers.ObjectSerializer' to type 'MongoDB.Bson.Serialization.IBsonSerializer'错误,本质是因为C#模型中field1和field2使用了object/List<object>类型。MongoDB驱动无法推断这些动态类型的内部结构,导致序列化器无法正确转换以支持嵌套字段的查询(比如myDatetime.ts)。
解决方案
方案1:定义具体的嵌套模型类(推荐)
放弃使用object,为嵌套对象创建明确的类,让MongoDB驱动能识别字段结构:
// 定义myDatetime的结构类 public record MyDatetime { public DateTime ts { get; init; } } // 定义field1的结构类 public record Field1Item { public string item1 { get; init; } public int item2 { get; init; } public MyDatetime myDatetime { get; init; } } // 定义field2的元素类 public record Field2Item { public double item11 { get; init; } public MyDatetime myDatetime { get; init; } } // 更新主模型 public record MongoCollection { public string ID { get; init; } public Field1Item field1 { get; init; } public List<Field2Item> field2 { get; init; } }
之后用强类型构建筛选器:
var filter = Builders<MongoCollection>.Filter.ElemMatch(x => x.field2, x => x.myDatetime.ts >= fromDate && x.myDatetime.ts <= tillDate);
方案2:使用BsonDocument手动构建查询(无需修改模型)
如果无法修改现有模型,直接用BsonDocument构造查询语句,绕过强类型序列化的限制:
var filter = new BsonDocument { { "field2", new BsonDocument { { "$elemMatch", new BsonDocument { { "myDatetime.ts", new BsonDocument { { "$gte", fromDate }, { "$lte", tillDate } } } } } } } };
额外注意点
你原代码中用ElemMatch处理field1是错误的——field1是单个对象而非数组,ElemMatch仅适用于数组字段。如果要筛选field1中的时间条件,直接使用普通的Gte/Lte即可:
var field1Filter = Builders<MongoCollection>.Filter.And( Builders<MongoCollection>.Filter.Gte("field1.myDatetime.ts", fromDate), Builders<MongoCollection>.Filter.Lte("field1.myDatetime.ts", tillDate) );
内容的提问来源于stack exchange,提问作者Iraj
相关产品推荐
相关产品推荐

