Mongo C#驱动程序:反序列化BsonValue

我在mongodb中有一个文档,结构类似于:

{ "_id": "abcdef01234", "Name": "Product A", "Dimensions": [ { "Height": 32, "Width": 64 }, { "Height": 16, "Width": 32 }, { "Height": 8, "Width": 16 } ] } 

我还有一个定义为表示维度的类(上面的子文档)

 public class Dimension { public int Height { get; set; } public int Width { get; set; } } 

我以这种方式选择“产品A”文档:

 MongoServer srv = MongoServer.Create(myConnStr); BsonDocument doc = srv["db"]["products"].FindOneById(ObjectId.Parse("abcdef01234")); BsonValue dimensionsVal = doc["Dimensions"]; 

现在我有一个名为dimensionsVal的BsonValue,它的类型为BsonArray。 我真正想要的是List 。 如何将dimensionsVal转换为List ?

编辑维度类实际上比我描述的要复杂得多。 由于内存问题,我希望将Dimensions与产品分开。 我想将产品保留在内存中,但不是(可能是巨大的)维度列表。 因此,我不希望将List作为Product类的属性。

以下是它的完成方式:

 using MongoDB.Bson.Serialization; MongoServer srv = MongoServer.Create(myConnStr); BsonDocument doc = srv["db"]["products"].FindOneById(ObjectId.Parse("abcdef01234")); BsonValue dimVal = doc["Dimensions"]; List d = BsonSerializer.Deserialize>(dimVal.ToJson()); 

试试这个:

 public class Product { [BsonId] public ObjectId Id { get; set; } public string Name{ get; set; } public List Dimensions{ get; set; } } public class DimensionDoc { public int Height { get; set; } public int Width { get; set; } } Product product = srv["db"]["products"].FindOneByIdAs(ObjectId.Parse("abcdef01234")); 

product.Dimensions现在将包含您需要的List <>。

更新:

您可能正在寻找包含/排除function。 在c#驱动程序中它完成了:

  // load products without array of Dimensions MongoCursorInstance.SetFields(Fields.Exclude("Dimensions")); //load empty product with Dimensions and _id MongoCursorInstance.SetFields(Fields.Include("Dimensions")); 

为什么不创建产品类? 在这种情况下,驱动程序将能够自动反序列化数据:

 class Product { [BsonId] public ObjectId Id { get; set; } public string Name{ get; set; } public List Dimensions{ get; set; } } var product = srv["db"]["products"].FindOneByIdAs(); var dimentions = product.Dimensions; 

但是如果你不想创建Product类,你可以这样:

 BsonArray dimensionsVal = doc["Dimensions"].AsBsonArray; var list = new List(); foreach (BsonValue value in dimensionsVal) { var bsonDoc = (BsonDocument) value; var d = new Dimension(); d.Height = bsonDoc["Height"]; d.Width = bsonDoc["Width"]; list.Add(d); } 

我会像其他人提出的那样,使用List 类型的Dimensions属性声明您的类。 然后,如果您想要读取没有 Dimensions值的Product,请写下:

 ObjectId productId; var query = Query.EQ("_id", productId); var fields = Fields.Exclude("Dimensions"); var product = collection.Find(query).SetFields(fields).FirstOrDefault(); // product.Dimensions will be null because there was no data for it 

当你想阅读包括所有Dimensions 在内的完整产品时,请写下:

 ObjectId productId; var query = Query.EQ("_id", productId); var product = collection.FindOne(query); // product.Dimensions will be populated this time 

这比将Dimensions读入BsonDocument并使用手写代码将它们转换为List 要高效得多。 这种方法导致两个数据副本被加载到内存中(尽管如果你没有保留对它的引用,可能很快就会收集BsonDocument版本)。