使用单向参考的人群中有许多人

时间:2014-01-18 23:15:44

标签: node.js mongodb mongoose many-to-many schema

我有以下用于表示多对多关系的模式:

var CategorySchema = new Schema({
  title: {type: String},    
});
mongoose.model('Category', CategorySchema);

var ProductSchema = new Schema({
  title: {type: String},
  categories: [
    {
      type: Schema.ObjectId,
      ref: 'Category'
    }
  ]
});
mongoose.model('Product', ProductSchema );

当我查询类别或产品时,我希望能够在结果中获得所有链接的文档。

在查询产品时填充类别非常简单:

Product.find().populate('categories').exec(...)

但是如何从类别方面做到这一点?我知道我可以在CategorySchema中的Product文档中添加一个ObjectId引用数组。但是我想避免双向引用(我不想维护它,并且存在不一致的风险)。

编辑:这是我实施的解决方案

/**
 * List all Categories
 */
exports.all = function (req, res) {
  //Function needed in order to send the http response only once all
  //the categories' product has been retrieved and added to the returned JSON document.
  function sendResponse(categories) {
    res.json(categories);
  }

  AppCategory.list(function (err, categories) {
    if (err) {
      errors.serverError();
    } else {
      _.forEach(categories, function (category, index) {
        category.products = [];
        Product.byCategory(category._id, function (err, products) {
          category.products= category.products.concat(products);
          if (index === categories.length - 1) {
            sendResponse(categories);
          }
        });
      });
    }
  });
};


ProductSchema.statics = {
  byCategory: function (categoryId, callback) {
    this.find({'categories': categoryId})
      .sort('-title')
      .exec(callback);
  }
};

1 个答案:

答案 0 :(得分:2)

你可能不想这样做。 :-)我猜一个产品可以在一些合理的少数类别中,但一个类别可能有数千种产品。在这种情况下,从效率的角度来看,尝试Category.populate('products')不会起作用。您将使用大量内存,无法以简单的方式进行分页,在产品属于多个类别时将重复的产品数据加载到内存中等等。通过直接查询产品集合来更好地加载产品类别。您可以轻松地按类别过滤la Product.find({'categories._id': $in: arrayOfCategoryIds}})