mongodb - MongoDB 和 Mongoose 正确模式
问题描述
我正在编写一个每天收集用户体重信息的应用程序。我是 NoSQL 数据库世界的新手。所以我想在一开始就选择正确的模式。
展示案例看起来是这样的:用户只说一次关键数据,例如身高或年龄,然后用户可以测量其重量
现在我是这样写的:
var userSchema = new Schema({
randomId: {type: Number, required: false, unique: true },
name: String,
userId: {type: String, required: true},
hight: Number,
gender: String,
waist: Number,
age: Number,
updated: { type: Date, default: Date.now }
});
如何存储每天的体重信息?
我应该用重量值和日期创建一个新的重量模型吗?
var weightSchema = new Schema({
name: String,
userId: {type: String, required: true},
weightValue:{
value: Number,
updated: { type: Date, default: Date.now }
}
});
或者我应该在每次记录 userSchema 时更新吗?
解决方案
实际上数据模型的设计取决于这个软件的要求(它如何使用数据)。
据我了解,用户-> 权重关系是一对多的映射。如果您只想存储用户信息及其权重而没有其他附加要求,那么您的模式是可以的。
因此,您将用户数据存储在用户集合中,一个用户对应一个文档。并且您有另一个集合来存储用户的体重数据,该集合中的多个文档属于一个用户。当你想获取一个用户和他的体重数据时,你必须查询2次:一次在用户集合中,另一次在权重集合中。
但是IMO,在设计数据模型时应该考虑其他方面:
表现
- 数据量?小块数据还是大量数据?
- 读/写百分比?
- 是否有用户会频繁访问的热点数据?
……
使用方便
我可以轻松更新/删除数据吗?
- …………
我将在下面的不同场景中给出一些建议:
1.您考虑读取性能,不会为一个用户存储太多的体重记录
您可以将用户模式和权重模式合并为一个模式,用户模式包含一个数组来存储用户的所有权重记录。这被称为 Mongodb 常用的非规范化模型。您的架构如下所示:
(我的电脑没有JS编程环境,所以不能确认是否可以编译没有错误,仅供参考。)
var weightSchema = new Schema({
value: Number,
updated: { type: Date, default: Date.now }
});
var userSchema = new Schema({
randomId: {type: Number, required: false, unique: true },
name: String,
userId: {type: String, required: true},
hight: Number,
gender: String,
waist: Number,
age: Number,
weights: [weightSchema], // Here are the weight records.
updated: { type: Date, default: Date.now }
});
mongoose.model('user', userSchema);
现在您只有一个集合来存储用户及其体重数据。一个用户一份文件。您可以获得一些好处:
- 更易于人类理解的数据模型
- 更高的读取性能,因为 mongodb 现在只需要查询一个集合。您可以通过获取一个文档来获取一个用户的所有数据。当用户添加新的体重记录时,您可以使用$push 。您可以通过$slice获取最旧的 N 条或最新的 N 条重量记录。
但同时你可能会遇到一些问题:
- 如果用户以非常高的频率添加他们的体重记录。用户集合中的文档大小将增长到非常大和快速。当原始保留空间不足时,这将导致移动文档在 mongodb 存储中的位置。这不利于写入性能。
- 您如何计算所有用户的平均/顶部/...权重?由于每个用户的体重数据是分开的,因此很难做到这一点。
2.你的用户有大量的体重数据,增长非常快。您需要计算用户的平均值/顶部/...。
请遵循您的原始设计。将数据存储在两个单独的集合中。
结论
有很多不同的建模方法,完全取决于您的要求。您可以查看 Mongodb 建模指南:https ://docs.mongodb.com/manual/core/data-modeling-introduction/
推荐阅读
- apache-kafka - Prometheus 如何刮取 Kafka 主题?
- apache-spark - 可以用 Apache Spark 代替 Sqoop
- gnu-make - 配方命令的彩色打印
- android - 有没有办法阻止底部导航在应用程序存在之前返回到每个访问过的选项卡?
- alexa - 问
话语在设备上不起作用,但在模拟器中起作用 - android - 在 OSM 地图上实现离线路由
- javascript - 错误:使用 Firebase 云功能时已超过最后期限
- javascript - 无法调用其类型缺少调用签名的表达式。输入'号码 | 派遣
>' 没有兼容的调用签名 - angular - 在角度7中单击模态内的链接后如何关闭模态
- python - 连接包含列表python的两列