首页 > 解决方案 > 在 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(),所以我不确定如何更新它们。

提前致谢!

标签: node.jsmongodbmongooseschema

解决方案


消息集合应该是独立的,不要将它嵌入到任何集合中。嵌入将无限增长的数据不是一个好主意。

将最后 5 条消息存储到其他集合中的想法看起来很难实现。

当您必须更新公会频道公会用户时,将来自所有集合的非规范化数据嵌入到用户集合中似乎是一个问题。

您可以将频道嵌入公会。频道不会无限制地增长,应该是一个合理的数量,每个公会少于 100 个频道,并且可能总是与他们所属的公会一起使用。如果没有,请考虑不要将频道嵌入公会

mongodb 的强大之处在于构建反映您的应用程序如何使用数据的模式。我建议从标准化数据开始。当创建、读取、更新、删除数据出现问题时,请在您的 mongoose 模式中进行适当的更改以解决问题。从长远来看,过早的优化只会造成伤害。

一如既往,答案取决于细节。由于我不知道所有细节,我会推荐 MongoDB 首席技术支持工程师 William Zola 的三篇文章。第 1 部分 第 2 部分 第 3 部分


推荐阅读