node.js - 在 Mongoose 上存储模式的正确方法?
问题描述
我开始学习一些 NodeJS,以及如何在 YouTube 上从 Academind 制作 REST API,并了解了关系数据库和非关系数据库是什么等。
使用 MongoDB,写入相当便宜,所以我想尽量减少读取次数。目前我正在尝试了解如何制作一个 API,这将是一个类似于 discord 的应用程序,尽管它会很有趣。
这是制作架构的正确方法吗?
const mongoose = require('mongoose')
const userSchema = mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
name: { type: String, required: true, unique: true},
email: { type: String, required: true },
password: { type: String, required: true }, // TODO: Hashing, etc
guilds: [{
_id: mongoose.Schema.Types.ObjectId,
name: {type: String, required: true},
channels: [{
_id: mongoose.Schema.Types.ObjectId,
name: {type: String, required: true},
// Only the X most recent messages
messages: [{
_id: mongoose.Schema.Types.ObjectId,
message: {type: String, required: true},
user: {
_id: mongoose.Schema.Types.ObjectId,
name: {type: String, required: true}
}
}]
}],
// Only an X amount of users
users: [{
_id: mongoose.Schema.Types.ObjectId,
name: {type: String, required: true}
}]
}]
})
module.exports = mongoose.model('User', userSchema)
然后对于公会,
const mongoose = require('mongoose')
const guildSchema = mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
name: {type: String, required: true},
channels: [{
_id: mongoose.Schema.Types.ObjectId,
name: {type: String, required: true},
// Only an X amount of messages
messages: [{
_id: mongoose.Schema.Types.ObjectId,
message: {type: String, required: true},
user: {
_id: mongoose.Schema.Types.ObjectId,
name: {type: String, required: true}
}
}]
}],
// All the users
users: [{
_id: mongoose.Schema.Types.ObjectId,
name: {type: String, required: true}
}]
})
module.exports = mongoose.model('Guild', guildSchema)
通道架构
const mongoose = require('mongoose')
const channelSchema = mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
name: { type: String, required: true },
guild: {
_id: mongoose.Schema.Types.ObjectId,
name: { type: String, required: true },
channels: [{
_id: mongoose.Schema.Types.ObjectId,
name: { type: String, required: true }
}],
// The users of the guild, or just the channel?
// Could add a users object outisde of the guild object
users: [{
_id: mongoose.Schema.Types.ObjectId,
name: { type: String, required: true }
}]
}
})
module.exports = mongoose.model('Channel', channelSchema)
最后是消息
const mongoose = require('mongoose')
const messageSchema = mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
user: {
_id: mongoose.Schema.Types.ObjectId,
name: {type: String, required: true}
},
message: {type: String, required: true},
channel: {
guild: {
_id: mongoose.Schema.Types.ObjectId,
name: {type: String, required: true}
// Store more data for each message?
}
}
})
module.exports = mongoose.model('Message', messageSchema)
我不确定这是否是非关系模式的样子。如果不是,我将如何存储我需要的数据?
另外,假设我在公会 Y 的频道 X 上与用户 AB 和 C 发布了一条消息,我将如何更新所有条目以添加一条消息?
到目前为止,我只使用了 User.find({_id: id}).exec().then().catch(),所以我不确定如何更新它们。
提前致谢!
解决方案
消息集合应该是独立的,不要将它嵌入到任何集合中。嵌入将无限增长的数据不是一个好主意。
将最后 5 条消息存储到其他集合中的想法看起来很难实现。
当您必须更新公会、频道、公会用户时,将来自所有集合的非规范化数据嵌入到用户集合中似乎是一个问题。
您可以将频道嵌入公会。频道不会无限制地增长,应该是一个合理的数量,每个公会少于 100 个频道,并且可能总是与他们所属的公会一起使用。如果没有,请考虑不要将频道嵌入公会。
mongodb 的强大之处在于构建反映您的应用程序如何使用数据的模式。我建议从标准化数据开始。当创建、读取、更新、删除数据出现问题时,请在您的 mongoose 模式中进行适当的更改以解决问题。从长远来看,过早的优化只会造成伤害。
一如既往,答案取决于细节。由于我不知道所有细节,我会推荐 MongoDB 首席技术支持工程师 William Zola 的三篇文章。第 1 部分 第 2 部分 第 3 部分
推荐阅读
- python - 在 google colab 中安装 ocrmypdf 时遇到问题
- sql - 尝试在 SQL 存储过程中有条件地更新字段
- shell - 可以在一行中从“xml_grep --count”获取var的计数吗?
- javascript - 动态创建和附加元素不起作用
- vba - Power Point VBA - 将图片从用户窗体复制到幻灯片
- html - 如何创建一个 Web 应用程序,在其中我可以根据下拉选择从工作表中读取文本?
- ruby-on-rails - 所有示例中的 Ruby on Rails 失败/错误
- azure-functions - 使用一组 Azure 函数和单个数据库创建整个后端应用程序有什么缺点?
- azure-storage - 如何为(REST API)天蓝色存储SAS(共享访问签名)构造标头
- python - 加载 keras 模型时产生的警告