如何避免MongoDB中Wrapper类数据重复存储且不影响查询?
解决MongoDB中Wrapper类数据重复存储的问题
针对你遇到的Wrapper类序列化后数据重复的问题,有两种可行的解决思路:
思路一:忽略内部WrappedThing的序列化,直接存储顶层Number字段
修改Wrapper类的私有字段WrappedThing,添加[BsonIgnore]标记阻止其序列化到数据库,同时为反序列化添加无参构造以初始化内部的Thing实例:
public class Wrapper { // 供MongoDB反序列化使用的无参构造 private Wrapper() { WrappedThing = new Thing(); } public Wrapper(Thing wrappedThing) { WrappedThing = wrappedThing; } public ObjectId Id { get; set; } // 标记为忽略序列化,不存入数据库 [BsonIgnore] private Thing WrappedThing { get; set; } public int Number { get => WrappedThing.Number; set => WrappedThing.Number = value; } }
这样数据库中只会存储_id和Number字段,不会出现重复数据。反序列化时,无参构造会自动初始化WrappedThing,MongoDB会将数据库中的Number值通过属性setter同步到内部的WrappedThing.Number中。
思路二:保留WrappedThing结构,映射顶层Number到嵌套字段
如果需要保留数据库中WrappedThing的嵌套结构,但不想重复存储Number值,可以通过手动配置类映射实现顶层Number与WrappedThing.Number的关联:
- 先移除顶层Number的
[BsonIgnore]标记,保留WrappedThing的[BsonElement]标记; - 在应用启动时注册类映射配置:
BsonClassMap.RegisterClassMap<Wrapper>(cm => { cm.AutoMap(); // 取消Number属性的默认序列化规则 cm.UnmapProperty(w => w.Number); // 手动将Number属性映射到数据库中的WrappedThing.Number路径 cm.MapMember(w => w.Number) .SetElementName("WrappedThing.Number") .SetSerializer(new Int32Serializer()); });
配置完成后,序列化时只会存储_id和嵌套的WrappedThing.Number,不会出现顶层Number字段;查询w => w.Number时,MongoDB会自动从WrappedThing.Number读取值,赋值时也会同步更新到内部的WrappedThing.Number,既避免了数据重复,又不会抛出查询异常。
内容的提问来源于stack exchange,提问作者piersb
相关产品推荐
相关产品推荐

