我在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”?
答案 0 :(得分:2)
为了deserialize class hierarchy,文档应该包含type discriminator字段,它告诉应该实例化哪种类型的子类。默认情况下,此字段的名称为_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