关系数据库设计到mongoDB/mongoose设计

RMK*_*147 6 javascript database-design mongoose mongodb node.js

我最近开始使用mongoDB和mongoose作为我的新node.js应用程序.在我努力适应mongoDB/noSQL思维方式(例如非规范化和缺乏外键关系)之前,只使用了关系数据库.我有这个关系数据库设计:

**Users Table**

user_id
username
email
password

**Games Table**

game_id
game_name

**Lobbies Table**

lobby_id
game_id
lobby_name

**Scores Table**

user_id
game_id
score
Run Code Online (Sandbox Code Playgroud)

因此,每个大厅属于一个游戏,多个大厅可以属于同一个游戏.用户对于不同的游戏也有不同的分数.到目前为止,对于我的用户架构,我有以下内容:

var UserSchema = new mongoose.Schema({
    username: {
        type: String,
        index: true,
        required: true,
        unique: true
    },
    email: {
        type: String,
        required: true
    },
    password: {
        type: String,
        required: true
    }
});
Run Code Online (Sandbox Code Playgroud)

所以我的问题是,如何将关系设计结构化为mongoDB/mongoose模式?谢谢!


编辑1

我现在尝试创建所有模式,但我不知道这是否是正确的方法.

var UserSchema = new mongoose.Schema({
    _id: Number,
    username: {
        type: String,
        index: true,
        required: true,
        unique: true
    },
    email: {
        type: String,
        required: true
    },
    password: {
        type: String,
        required: true
    },
    scores: [{ type: Schema.Types.ObjectId, ref: 'Score' }]
});

var GameSchema = new mongoose.Schema({
    _id: Number,
    name: String
});

var LobbySchema = new mongoose.Schema({
    _id: Number,
    _game: { type: Number, ref: 'Game' },
    name: String
});

var ScoreSchema = new mongoose.Schema({
    _user : { type: Number, ref: 'User' },
    _game : { type: Number, ref: 'Game' },
    score: Number
});
Run Code Online (Sandbox Code Playgroud)

小智 11

Mongoose的设计方式使您可以相对轻松地对表进行关系建模,并根据ref您在模式中定义的关系数据填充关系数据.问题是你需要小心填充.如果您填充太多或嵌套您的人口,您将遇到性能瓶颈.

你的做法Edit 1是正确的大幅但是你通常不希望来填充远程ref基于一个Number或设置_id一个模型的一种Number,因为蒙戈使用它自己的哈希机制来管理_id,这通常会是一个ObjectId_id暗示.示例如下所示:

var ScoreSchema = new mongoose.Schema({
    user : { type: Schema.Types.ObjectId, ref: 'User' },
    game : { type: Schema.Types.ObjectId, ref: 'Game' },
    score: Number
});
Run Code Online (Sandbox Code Playgroud)

如果由于某种原因你需要为你的记录保留一个数字id,考虑调用它uid或不会与mongo/mongoose内部冲突的东西.祝好运!


Lev*_*mov 5

首先,你在这里找到了一些好点。Mongoose 的美妙之处在于您可以轻松地将模式连接和绑定到单个集合,并在其他集合中引用它们,从而充分利用关系和非关系数据库。

此外,您不会将 _id 作为属性之一,Mongo 会为您添加它。

我已经使用该mongoose.Schema.Types.ObjectId类型对您的架构进行了一些更改。

var UserSchema = new mongoose.Schema({
    username: {
        type: String,
        index: true,
        required: true,
        unique: true
    },
    email: {
        type: String,
        required: true
    },
    password: {
        type: String,
        required: true
    },
    scores: [{ type: Schema.Types.ObjectId, ref: 'Score' }]
});

var GameSchema = new mongoose.Schema({
    name: String
});

var LobbySchema = new mongoose.Schema({
    _game: { 
       type: mongoose.Schema.Types.ObjectId, 
       ref: 'Game' 
     },
    name: String
});

var ScoreSchema = new mongoose.Schema({
    _user : { 
         type: mongoose.Schema.Types.ObjectId, 
         ref: 'User' 
       },
    _game : { 
         type: mongoose.Schema.Types.ObjectId, 
         ref: 'Game' 
       },
    score: Number
});
Run Code Online (Sandbox Code Playgroud)

这将允许您查询数据库并填充任何引用的集合和对象。

例如:

ScoreSchema.find({_id:##userIdHere##})
           .populate('_user')
           .populate('_game')  
           .exec(function(err, foundScore){
                   if(err){
                      res.send(err)
                    } else {
                 res.send(foundScore)
   }
}
Run Code Online (Sandbox Code Playgroud)

这将填充相关的用户和游戏属性。


Chr*_*ris 0

两种方式(据我所知)。您存储一个 id(已索引),一旦查询第一个表,您就可以查询第二个表以从中获取信息,因为没有连接。这意味着,如果您从一张表中获取用户 ID,则需要对用户表进行多次查询才能获取用户的数据。

另一种方法是将其全部存储在一个表中,即使它是重复的。例如,如果您需要存储的只是用户的屏幕名称和其他内容,那么只需将其与其他数据一起存储,即使它已经存在于用户表中。我相信其他人会知道更好/不同的方法。