Драйвер Mongo C #: десериализация BsonValue - PullRequest
10 голосов
/ 15 июля 2011

У меня есть документ в 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; }
}

Я выбираю документ «Продукт А» следующим образом:

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

Теперь у меня есть BsonValue с именем sizesVal, который имеет тип BsonArray.Что я действительно хочу, так это список .Как преобразовать измерения ValV в Список ?

Редактировать Класс измерений на самом деле значительно сложнее, чем я описал.Я хочу отделить Измерения от Продукта из-за проблем с памятью.Я хочу сохранить Продукт в памяти, но не (потенциально огромный) список измерений.По этой причине я не хочу, чтобы List был свойством класса Product.

Ответы [ 4 ]

20 голосов
/ 15 июля 2011

Вот как это можно сделать:

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());
3 голосов
/ 15 июля 2011

Обновление:

Вы, вероятно, ищете функциональность включения / исключения . В драйвере 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<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);
}
3 голосов
/ 15 июля 2011

Попробуйте это:

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 теперь будет содержать список <>, который вам нужен.

1 голос
/ 15 июля 2011

Я бы объявил ваш класс со свойством Dimensions типа List , как предлагали другие. Затем, если вы хотите прочитать продукт без , значения Dimensions напишите так:

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

Это будет намного эффективнее, чем чтение Размеров в BsonDocument и преобразование их в Список с рукописным кодом. Этот подход приводит к тому, что две копии данных загружаются в память (хотя, предположительно, версия BsonDocument будет вскоре после этого собрана сборщиком мусора, если вы не сохраните ссылку на нее).

...