Mongo c#驱动程序:反序列化BsonValue
本文关键字:反序列化 BsonValue 驱动程序 Mongo | 更新日期: 2023-09-27 18:02:03
我在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; }
}
我以这种方式选择"Product A"文档:
MongoServer srv = MongoServer.Create(myConnStr);
BsonDocument doc = srv["db"]["products"].FindOneById(ObjectId.Parse("abcdef01234"));
BsonValue dimensionsVal = doc["Dimensions"];
现在我有一个名为dimensionsVal的BsonValue,它的类型是BsonArray。我真正想要的是一个List
编辑维度类实际上比我所描述的要复杂得多。由于内存问题,我希望将Dimensions与Product分开。我希望将Product保存在内存中,而不是(可能非常庞大的)维度列表。由于这个原因,我不想把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<Dimension> d = BsonSerializer.Deserialize<List<Dimension>>(dimVal.ToJson());
更新:
你可能在寻找包含/排除功能。在c#驱动程序中是这样做的:
// load products without array of Dimensions
MongoCursorInstance.SetFields(Fields.Exclude("Dimensions"));
//load empty product with Dimensions and _id
MongoCursorInstance.SetFields(Fields.Include("Dimensions"));
为什么不直接为product创建类呢?在这种情况下,驱动程序将能够自动反序列化数据:
class Product
{
[BsonId]
public ObjectId Id { get; set; }
public string Name{ get; set; }
public List<Dimension> Dimensions{ get; set; }
}
var product = srv["db"]["products"].FindOneByIdAs<Product>();
var dimentions = product.Dimensions;
但是如果你不想创建Product
类,你可以这样做:
BsonArray dimensionsVal = doc["Dimensions"].AsBsonArray;
var list = new List<Dimension>();
foreach (BsonValue value in dimensionsVal)
{
var bsonDoc = (BsonDocument) value;
var d = new Dimension();
d.Height = bsonDoc["Height"];
d.Width = bsonDoc["Width"];
list.Add(d);
}
试试这个:
public class Product
{
[BsonId]
public ObjectId Id { get; set; }
public string Name{ get; set; }
public List<DimensionDoc> Dimensions{ get; set; }
}
public class DimensionDoc
{
public int Height { get; set; }
public int Width { get; set; }
}
Product product = srv["db"]["products"].FindOneByIdAs<Product>(ObjectId.Parse("abcdef01234"));
产品。尺寸现在将包含您需要的List<>
我将使用类型为List
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
当你想阅读完整的产品包括所有的尺寸时,写这个:
ObjectId productId;
var query = Query.EQ("_id", productId);
var product = collection.FindOne(query);
// product.Dimensions will be populated this time
这比将Dimensions读入BsonDocument并使用手写代码将其转换为List