用于多个auth用户帐户的MongoDB架构设计

Sve*_*ven 31 mongoose mongodb express passport.js

我即将构建我的node.js/express/mongoose/passport应用程序,我正在考虑为用户和帐户设置正确的架构.

将有用户从Twitter和Facebook以及本机帐户登录.在稍后阶段,我希望用户将twitter和facebook连接到我的应用程序(可能还有更多的外部帐户).

对于那种情况,我想不出一个好的解决方案.以下是我想到的选项:

1.拥有个人资料模型和帐户模型.配置文件代表唯一用户,而帐户提供用户名和密码(内部帐户)或来自身份验证提供程序(外部帐户)的身份验证数据.配置文件必须至少有一个嵌套的帐户文档.

var ExtAccountSchema = new Schema({
    type: String, // eg. twitter, facebook, native
    uid: String
});

var IntAccountSchema = new Schema({
    username: String,
    password: String
});

var ProfileSchema = new Schema({
    firstname: String,
    lastname: String,
    email: String,
    accounts: [Account] // Pushing all the accounts in there
});
Run Code Online (Sandbox Code Playgroud)

我不喜欢它的是由不同的帐户数据导致的不一致的帐户文档以及我在用户登录时难以找到合适的帐户(在嵌套文档中搜索uid和帐户类型-.-)的事实

2.将所有数据保存在单个模型中

var ProfileSchema = new Schema({
    firstname: String,
    lastname: String,
    email: String,        
    twitter-uid: String,
    facebook-uid: String
    password: String
});
Run Code Online (Sandbox Code Playgroud)

嗯,这只是丑陋 - .-找到合适的帐户数据可能更容易/更快,但维护起来并不好.

有更好的解决方案吗?有最好的做法吗?

Wil*_*m Z 49

1)您可以采用三种策略来构建MongoDB中的数据:

  • a)嵌入文档的数组
  • b)嵌入式引用的数组
  • c)扩展到父文档中

策略(a)是您描述的第一个,其中Profile文档包含一系列Account子文档.

策略(b)类似于策略(a),但您使用一系列对其他文档的引用(通常在Account集合中),而不是嵌入实际文档.

策略(c)是您描述为"在单个模型中拥有所有数据"的策略.

2)通常认为使用嵌入式文档数组的最佳实践,尤其是当它们中的信息可能不同时.如果它会让您的生活更轻松,您可以使用键来区分帐户的类型,如下所示:

  { 
    firstname: 'Fred',
    lastname: 'Rogers',
    email: 'fred.rogers@example.com',

    accounts: [
             { kind: 'facebook',
               uid: 'fred.rogers'
             },
             { kind: 'internal',
               username: 'frogers',
               password: '5d41402abc4b2a76b9719d911017c592'
             },
             { kind: 'twitter',
               uid: 'fredr'
             }
          ]
    }
Run Code Online (Sandbox Code Playgroud)

3)MongoDB允许您搜索嵌入的文档.所以你会写下面的查询(JavaScript语法):

 db.profile.find( 
        { email: 'fred.rogers@example.com', 'accounts.kind': 'facebook' }
        );
Run Code Online (Sandbox Code Playgroud)

使用适当的索引,此查询将非常快.