Mongo C#Driver:Deserialize BsonArray
本文关键字:BsonArray Deserialize C#Driver Mongo | 更新日期: 2023-09-27 18:36:37
>我在mongodb中有一个文档,其结构类似于:
{
"_id":xxxxx,
"business":[{
"subBusiness":[{
"subBusinessName":"Abusiness",
"a":"aaaa"
},{
"subBusinessName":"Bbusiness",
"b":"bbbbb",
"c":"ccccc"
}]
}]
}
如何制作映射类来序列化此文档?
我还有一个定义用于表示维度的类(上面的子文档)
class STObject{
[BsonId]
public ObjectId id{get;set;}
[BsonElement("business")]
public List<Business> BusinessList{get;set;}
}
class Business {
[BsonElement("subBusiness")]
public List<SubBusiness> SubBuiness { get; set; }
}
[BsonDiscriminator(RootClass = true)]
[BsonKnownTypes(typeof(CSSubBusiness),typeof(ApproSubBusiness))]
public class SubBusiness {
[BsonElement("subBusinessName")]
public string SubBusinessName{get;set;}
}
public class AsubBusiness:SubBusiness{
[BsonElement("a")]
public string A{get;set;}
}
public class BsubBusiness:SubBusiness{
[BsonElement("b")]
public string B{get;set;}
[BsonElement("c")]
public string C{get;set;}
}
如何在类 STObject 中查询元素"b"?
为了反序列化类层次结构,文档应包含类型鉴别器字段,该字段告知应实例化哪种类型的子类。默认情况下,此字段的名称为 _t
。但是,如果您已经拥有具有上述模式的文档并且无法更改它,那么您应该覆盖 Mongo 使用的鉴别器约定。
看起来您可以将subBusinessName
字段用作子业务类型的类型鉴别器。为此,您应该从基本类型中删除此字段:
[BsonDiscriminator(RootClass = true)]
[BsonKnownTypes(typeof(AsubBusiness), typeof(BsubBusiness))] // btw check types
public class SubBusiness
{
}
并且您应该为子类型提供鉴别器值:
[BsonDiscriminator("Abusiness")] // provide discriminator value here
public class AsubBusiness : SubBusiness
{
[BsonElement("a")]
public string A { get; set; }
}
[BsonDiscriminator("Bbusiness")]
public class BsubBusiness : SubBusiness
{
[BsonElement("b")]
public string B { get; set; }
[BsonElement("c")]
public string C { get; set; }
}
最后一步 - 创建自定义约定,使 mongo 查看此鉴别器字段以实例化正确的子类类型:
public class SubBusinessDiscriminatorConvention : IDiscriminatorConvention
{
public string ElementName
{
get { return "subBusinessName"; }
}
public Type GetActualType(BsonReader bsonReader, Type nominalType)
{
var bookmark = bsonReader.GetBookmark();
bsonReader.ReadStartDocument();
var actualType = nominalType;
if (bsonReader.FindElement(ElementName))
{
var discriminator = (BsonValue)BsonValueSerializer.Instance.Deserialize(bsonReader, typeof(BsonValue), null);
actualType = BsonSerializer.LookupActualType(nominalType, discriminator);
}
bsonReader.ReturnToBookmark(bookmark);
return actualType;
}
public BsonValue GetDiscriminator(Type nominalType, Type actualType)
{
var classMap = BsonClassMap.LookupClassMap(actualType);
return classMap.Discriminator;
}
}
现在为基类型序列化设置此约定:
BsonSerializer.RegisterDiscriminatorConvention(typeof(SubBusiness),
new SubBusinessDiscriminatorConvention());
您可以以确切的格式序列化和反序列化文档。
更新:查询:
var collection = test.GetCollection<STObject>("collectionName");
var sto = collection.FindOne(Query.EQ("_id", new ObjectId("xxxxx")));
var businessList = sto.BusinessList.FirstOrDefault();
var bsub = businessList.SubBuiness.OfType<BsubBusiness>().FirstOrDefault();
var b = bsub.B; // returns bbbbb