如何在不同的mongodb集合中存储嵌套对象?

时间:2010-08-23 09:17:04

标签: mongodb norm

我需要存储这些类的一些对象:

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并存储Category对象时 。mongo.GetCollection()插入(类别); 我可以在mongo shell中看到:

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 个答案:

答案 0 :(得分:2)

不,你不能。至少不是自动的。

SQL数据库最适合在多个表中存储规范化数据。表之间的关系由外键关系定义。 NHibernate使用这些外键关系将对象映射到多个表。

MongoDB适用于存储文档。这些文档通常是数据的非规范化表示。这个想法是将相关数据存储在单个文档中而不是多个表中。由于这种理念,MongoDB不需要外键概念或加入集合的能力。

理论上,NoRM将来可以支持这种功能,但这违背了文档数据库的精神。所以它不太可能得到支持。

手动解决方案

通过应用Products属性,您可以告诉NoRM在保存类别时跳过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属性将指示产品所属的类别。