Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mongo C# Driver: Deserialize BsonValue

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

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

I also have a class defined to represent dimensions (the sub document from above)

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

I am selecting the "Product A" document in this manner:

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

Now I have a BsonValue named dimensionsVal which is of type BsonArray. What I really want is a List<Dimension>. How do I convert dimensionsVal to a List<Dimension>?

Edit The dimension class is actually significantly more complex than what I described. I want to keep the Dimensions separate from the Product because of memory concerns. I want to keep the Product in memory, but not the (potentially enormous) list of dimensions. For this reason, I don't want to have a List as a property of the Product class.

like image 824
Joel Harris Avatar asked Jul 14 '11 22:07

Joel Harris


People also ask

What is Mongo C?

The MongoDB C Driver, also known as “libmongoc”, is a library for using MongoDB from C applications, and for writing MongoDB drivers in higher-level languages. It depends on libbson to generate and parse BSON documents, the native data format of MongoDB.

What is a Mongo driver?

The official MongoDB Node. js driver allows Node. js applications to connect to MongoDB and work with data. The driver features an asynchronous API which allows you to interact with MongoDB using Promises or via traditional callbacks.


2 Answers

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());
like image 89
Joel Harris Avatar answered Oct 18 '22 11:10

Joel Harris


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);
}
like image 40
Andrew Orsich Avatar answered Oct 18 '22 12:10

Andrew Orsich