首页 文章

构建我的mongoose模式的最佳方法:嵌入式数组,填充,子文档?

提问于
浏览
8

这是我目前的Schema

牌:

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}
});

帖子:

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 populate功能:

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

然而,这是一个菜鸟 - 我开始阅读有关mongoose populate的性能问题,因为它实际上只是添加了一个额外的查询 .

对于我的帖子,特别是,似乎可能会很费力 . 这篇文章的目的是成为一个真实的推特/ Instagram类似的饲料 . 似乎可能是很多查询,这可能会大大减慢我的应用程序 .

此外,我希望能够在某些时候按字段搜索产品/帖子/品牌 .

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

什么是最有效的架构设计或我的设置是否正常 - 鉴于我已指定我想用它?


User story:

There will be an Admin User.

管理员可以使用品牌架构中的特定字段添加品牌 .

品牌将有相关的产品,每个产品将有一个样式/类别 .


Search:

用户将能够按名称和位置搜索品牌(我正在考虑使用角度过滤/标签进行此操作) .

用户将能够按字段(名称,样式等)搜索产品 .

用户将能够按品牌产品和样式进行搜索 .


Post:

用户可以发布到Feed中 . 在制作帖子时,他们会选择一个品牌和一个产品来关联帖子 . 帖子将显示品牌名称,产品名称和样式 - 以及新输入的帖子字段(照片,评论和评级) .

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

Product show page:

将显示上述架构中的产品字段 - 包括样式架构中的关联样式名称 . 它还将显示与特定产品相关的帖子 .

Brand show page:

将简单地显示品牌字段和相关产品 .


我主要担心的是Post,它必须填充/查询Feed中的品牌,产品和样式 .

再一次,我正在考虑是否应该将产品嵌入品牌中 - 那么我是否能够将品牌产品和样式与帖子相关联以便以后查询?或者,可能是$ lookup或其他聚合功能 .

1 回答

  • 6

    Mongodb本身不支持连接 . 因此,mongoose populate是一种外部参考分辨率的尝试 . 使用mongodb的是你需要设计你的数据,以便:

    • 大多数查询都不需要引用多个集合 .
      从查询中获取数据后
    • ,您无需对其进行过多的转换 .

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

    • 品牌是品牌 . 不依赖于其他任何东西 .

    • 每件产品都属于一个品牌 .

    • 每个产品都与样式相关联 .

    • 每个帖子都与产品相关联 .

    • 间接地,每个帖子都通过产品与品牌和风格相关联 .

    关于用例:

    • Refer: 如果您通过id查找一个实体,那么获取1-2个相关实体并不是一个很大的开销 .

    • List: 当您必须返回大量对象时,每个对象都需要一个额外的查询来获取关联对象 . 这是一个性能问题 . 这通常通过一次处理结果集的"pages"来减少,比如说每个请求20个记录 . 让我们假设您查询20个产品(使用 skiplimit ) . 对于20种产品,您可以提取两个id数组,一个引用的样式和其他引用的品牌 . 您使用 $in:[ids] 执行2个其他查询,获取品牌和样式对象并将它们放在结果集中 . 这是每页3个查询 . 用户可以在向下滚动时请求下一页,依此类推 .

    • Search: 您想要搜索产品,但也想要指定品牌名称和样式名称 . 可悲的是,产品型号只适用于款式和品牌 . 与品牌和产品一起搜索帖子的问题相同 . 流行的解决方案是维护一个单独的"search index",一种表,它可以完全按照搜索方式存储数据,并在一个地方显示所有可搜索的字段(如品牌名称,样式名称) . 手动维护mongodb中的搜索集合可能会很麻烦 . 这就是ElasticSearch的用武之地 . 由于你已经在使用mongoose,你可以简单地将mongoosastic添加到你的模型中 . ElasticSearch的搜索功能远远超过数据库存储引擎为您提供的功能 .

    • Extra Speed: 还有一些加速的空间:缓存 . 附加mongoose-redis-cache并在Redis内存中频繁重复查询,减少mongodb上的负载 .

    • Twitter like Feeds: 现在,如果所有帖子都是公开的,那么按时间顺序为用户列出它们是一个简单的查询 . 但是,当您引入"social networking"功能时,情况会发生变化 . 然后你需要列出"activity feeds"的朋友和追随者 . 关于社交收件箱和扇出列表有一些智慧in mongodb blog .

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

相关问题