最好的方式来构build我的mongoose模式:embedded式数组,填充,子文档?

这是我目前的模式

牌:

var mongoose = require('mongoose'); var Schema = mongoose.Schema; var BrandSchema = new mongoose.Schema({ name: { type: String, lowercase: true , unique: true, required: true }, photo: { type: String , trim: true}, email: { type: String , lowercase: true}, year: { type: Number}, timestamp: { type : Date, default: Date.now }, description: { type: String}, location: { }, social: { website: {type: String}, facebook: {type: String }, twitter: {type: String }, instagram: {type: String } } }); 

样式:

 var mongoose = require('mongoose'); var Schema = mongoose.Schema; var StyleSchema = new mongoose.Schema({ name: { type: String, lowercase: true , required: true}, }); 

产品

 var mongoose = require('mongoose'); var Schema = mongoose.Schema; var ProductSchema = new mongoose.Schema({ name: { type: String, lowercase: true , required: true}, brandId : {type: mongoose.Schema.ObjectId, ref: 'Brand'}, styleId: {type: mongoose.Schema.ObjectId, ref: 'Style'}, year: { type: Number }, avgRating: {type: Number} }); 

post:

 var mongoose = require('mongoose'); var Schema = mongoose.Schema; var PostSchema = new mongoose.Schema({ rating: { type: Number}, upVote: {type: Number}, brandId : {type: mongoose.Schema.ObjectId, ref: 'Brand'}, comment: {type: String}, productId: {type: mongoose.Schema.ObjectId, ref: 'Style'}, styleId: {type: mongoose.Schema.ObjectId, ref: 'Style'}, photo: {type: String} }); 

我目前正在使用mongoose填充function:

 exports.productsByBrand = function(req, res){ Product.find({product: req.params.id}).populate('style').exec(function(err, products){ res.send({products:products}); }); }; 

但是,这是一个noob —我已经开始阅读与mongoose填充性能问题,因为它只是添加一个额外的查询。

特别是对于我的文章来说,似乎可能会导致征税。 这个post的意图是成为一个活的twitter / instagram的饲料。 这似乎可能是很多的查询,这可能会大大减缓我的应用程序。

另外,我希望能够在某个时候按字段search产品/post/品牌。

我应该考虑嵌套/embedded这些数据(产品嵌套/embedded品牌)?

什么是最有效的模式devise,或者我的设置是否正确 – 给我指定我想要使用它?


用户故事:

将有一个pipe理员用户。

pipe理员可以将品牌添加到品牌架构中的特定字段。

品牌将有相关的产品 ,每个产品将有一个风格 /类别。


search:

用户将能够search品牌的名称和位置(我正在考虑做这个angular度过滤/标签)。

用户将能够通过字段(名称,样式等)search产品

用户将能够search品牌 产品风格


post:

用户将能够张贴到一个饲料。 在创build邮政时 ,他们会select一个品牌和一个产品来将邮政关联起来。 邮政将显示品牌名称, 产品名称和样式 – 以及新input的邮政领域(照片,评论和评级)。

其他用户可以点击品牌名称链接到品牌展示页面。 他们可以点击产品名称链接到产品展示页面。

产品展示页面:

将显示上述架构的产品字段 – 包括来自Style架构的关联样式名称。 它还将显示与特定产品有关的post

品牌展示页面:

将只显示品牌领域和相关产品。


我主要担心的是邮政 ,它必须在饲料中填充/查询品牌产品风格

再次,我正在考虑是否应该将产品embedded品牌 – 那么我能否将品牌 产品风格邮政联系起来,以便以后查询? 或者,也许$查找或其他聚合function。

Mongodb本身不支持连接。 所以,mongoose填充是对外部参考分辨率的尝试。 与mongodb的事情是,你需要devise你的数据,以便:

  1. 大多数查询不需要引用多个集合。
  2. 从查询中获取数据后,不需要太多的转换。

考虑所涉及的实体及其关系:

  1. 品牌就是品牌。 不依赖于其他任何东西。
  2. 每个产品都属于一个品牌。
  3. 每个产品都与样式相关联。
  4. 每个post都与一个产品相关联。
  5. 间接地,每个post通过产品与品牌和风格相关联。

现在介绍一下用例:

  1. 参考:如果你正在查找一个实体的ID,然后提取1-2相关的实体并不是一个真正的大开销。

  2. 列表:这是当你必须返回一大组对象,每个对象需要一个额外的查询来获取关联的对象。 这是一个性能问题。 这通常通过一次处理结果集的“页面”来减less,例如每个请求20个logging。 让我们假设你查询了20个产品(使用skiplimit )。 对于20个产品,您可以提取两个id数组,其中一个引用的样式,以及其他引用的品牌。 您使用$in:[ids]执行另外2个查询,获取品牌和样式对象,并将它们放置在结果集中。 这是每页3个查询。 用户可以向下滚动时请求下一页,依此类推。

  3. search:您要search产品,但也要指定品牌名称和样式名称。 可悲的是,产品模型只保留风格和品牌的ID。 与品牌和产品searchpost相同的问题。 stream行的解决scheme是维护一个单独的“search索引”,一种表格,它将数据完全按照search的方式进行存储,所有可search的字段(如品牌名称,样式名称)在同一个位置。 手动维护MongoDB中的search集合可能是一个痛苦。 这就是ElasticSearch的用武之地。既然你已经在使用mongoose了,你可以简单的在模型中joinmongoosastic 。 ElasticSearch的search能力远远超过DB存储引擎为您提供的function。

  4. 额外速度:还有一些加速的地方:caching。 附上mongoose-redis-cache ,并频繁地重复查询,从Redis的内存中,减轻了对MongoDB的负载。

  5. Twitter的喜欢饲料:现在,如果所有的职位都是公开的,那么按时间顺序列出他们是一个微不足道的查询。 不过,当你引入“社交networking”function时,情况就会改变。 那么你需要列出朋友和追随者的“活动馈送”。 在MongoDB博客中有关于社交收件箱和Fan-out列表的一些智慧。

道德的故事是,并不是所有的用例都只有“db schema query”解决scheme。 可伸缩性就是这种情况之一。 这就是为什么存在其他工具。