Mongo C# Driver: Deserialize BsonValue

前端 未结 4 1067
忘掉有多难
忘掉有多难 2021-02-05 15:42

I have a document in mongodb that is structured similar to this:

{
  \"_id\": \"abcdef01234\",
  \"Name\": \"Product A\",
  \"Dimensions\": [
    {
      \"Heigh         


        
相关标签:
4条回答
  • 2021-02-05 16:22

    Try this:

    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"));
    

    product.Dimensions will now contain the List<> you need.

    0 讨论(0)
  • 2021-02-05 16:27

    I would declare your class with a Dimensions property of type List<Dimension> as others have proposed. Then if you want to read a Product without the Dimensions values write this:

    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
    

    and when you want to read the full product including all of the Dimensions write this:

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

    This will be much more efficient than reading the Dimensions into a BsonDocument and converting them to a List<Dimension> with hand-written code. That approach results in two copies of the data being loaded in memory (although presumably the BsonDocument version will be garbage collected soon thereafter if you don't keep a reference to it).

    0 讨论(0)
  • 2021-02-05 16:31

    Update:

    You probably looking for include/exclude functionality. In c# driver it done so:

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

    Why not just create class for product? In this case driver will be able to deserialize data automatically :

    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;
    

    But if you don't want create Product class you can go this way:

    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);
    }
    
    0 讨论(0)
  • 2021-02-05 16:32

    Here is how it can be done:

    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());
    
    0 讨论(0)
提交回复
热议问题