Как хранить вложенные объекты в разных коллекциях mongodb? - PullRequest
2 голосов
/ 23 августа 2010

Мне нужно хранить некоторые объекты этого класса:

public class Category{
    public ObjectId Id {get;set;}
    public string Name {get;set;}
    public string Description {get;set;}
    public List<Product> Products {get;set;}
}

public class Product{
    public ObjectId Id {get;set;}
    public string Name {get;set;}
    public string Description {get;set;}
    public decimal Price {get;set;}
}

Когда я использую NoRM и сохраняю объект категории с . Mongo.GetCollection () Вставка (Категория); Я вижу в оболочке монго:

db.Category.find()
{ "_id" : ObjectId("82bbbf0179eae0141d020000"), "Name" : "Test products", "Descr
iption" : "This is test category", "Products" : [
        {
                "_id" : ObjectId("81bbbf0179eae0141d000000"),
                "Name" : "Product1",
                "Description" : "first product",
                "Price" : {

                }
        },
        {
                "_id" : ObjectId("82bbbf0179eae0141d010000"),
                "Name" : "Product2",
                "Description" : "second product",
                "Price" : {

                }
        }
] }

Могу ли я хранить объекты Category и Product в разных коллекциях и иметь только ссылку на Product в записи категории без изменения кода классов? (Как в NHibernate)

1 Ответ

2 голосов
/ 23 августа 2010

Нет, вы не можете.По крайней мере, не автоматически.

Базы данных SQL лучше всего подходят для хранения нормализованных данных в нескольких таблицах.Отношения между таблицами определяются отношениями внешних ключей.NHibernate использует эти отношения внешнего ключа для сопоставления объектов с несколькими таблицами.

MongoDB предназначен для хранения документов.Эти документы обычно представляют собой денормализованное представление данных.Идея состоит в том, чтобы хранить связанные данные в одном документе вместо нескольких таблиц.В результате этой философии MongoDB не нуждается ни в концепциях внешних ключей, ни в возможности объединения коллекций.

Теоретически NoRM может поддерживать такую ​​функциональность в будущем, но это противоречит духу баз данных документов.Поэтому маловероятно, что он когда-либо будет поддерживаться.

Решение вручную

Вы можете указать NoRM пропустить свойство Products при сохранении категории, применив атрибут MongoIgnore.Затем сохраните продукты вручную в отдельной коллекции вместе с «ссылкой» на категорию.Вы можете автоматически отслеживать категорию товаров, используя пользовательскую коллекцию.Код будет выглядеть примерно так:

public class ProductCollection : Collection<Product>
{
  private Category owner;

  public ProductCollection(Category owner)
  {
    // Remember who 'owns' the products in this collection.
    this.owner = owner;
  }

  protected override void InsertItem(int index, Product item)
  {
    // Tell the product to which category it belongs.
    item.CategoryId = this.owner.Id;

    base.InsertItem(index, item);
  }

  // Override other methods using the same pattern.
}

public class Category
{
  public Category()
  {
    this.Id = ObjectId.NewObjectId();
    this.Products = new ProductCollection(this);
  }

  public ObjectId Id { get; set; }
  public string Name { get; set; }
  public string Description { get; set; }

  [MongoIgnore]
  public ProductCollection Products { get; private set; }
}

public class Product
{
  public ObjectId Id { get; set; }
  public string Name { get; set; }
  public string Description { get; set; }
  public decimal Price { get; set; }
  public ObjectId CategoryId { get; set; }
}

Теперь вы можете хранить категории в одной коллекции, а продукты - в другой коллекции.Свойство CategoryId будет указывать категорию, к которой относится продукт.

...