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

时间:2012-06-19 13:26:44

标签: mongodb express mongoose passport.js

我即将构建我的node.js / express / mongoose / 通信应用程序,我正在考虑正确的架构设计用户和帐户。

将有用户从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
});

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

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

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

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

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

2 个答案:

答案 0 :(得分:46)

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'
             }
          ]
    }

3)MongoDB允许您搜索嵌入的文档。因此,您将编写以下查询(JavaScript语法):

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

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

答案 1 :(得分:0)

我希望它可以帮助像您这样有类似需求的人。

MongoDB中的架构设计和数据建模

  • SQL具有固定/严格模式,而NoSQL具有动态/灵活模式,即不强制执行文档结构

  • MongoDB有两种类型的数据模型:

    • 嵌入式数据建模:
      • 具有单一文档结构,被称为非规范化模型
      • 支持文档级原子操作。
      • 易于执行CRUD
      • 使用了70%的案例,并且在读取操作中表现出色
      • 大小可以轻松达到其阈值,即16 MB,并且易于实现高冗余性
      • 建议以一对一和一对多的关系
    • 参考或链接数据建模
      • 模仿SQL数据库的规范化表,以减少数据重复和冗余。
      • reference或_id用于引用另一个文档,该文档类似于使用主键和外键在SQL中联接表。
      • 在30%的案例中使用
      • 推荐用于多对多关系

数据建模的观点

  • 概念数据建模:有关功能和服务的大图片,其中还包括
    • ER数据建模:数据库设计的图形方法。
    • 架构设计
  • 逻辑数据建模:将使用编程语言,表等(服务器代码)将概念数据建模转换为逻辑数据建模(程序)
  • 物理数据建模:将逻辑DM付诸实践,由其用户插入实际数据。(数据库)

数据模型的类型

  • 平面,星形,层次,关系,对象关系

文档之间的模型关系

  • 通常,您应该构建架构,以便您的应用程序在一次读取操作中即可接收其所有必需的信息。

与嵌入式文档建立一对一关系

  - In referenced or normalized data model, If one document is frequetly refering some data in another document, It would create better data model to embed both documents into one.
  - If a single document seems to be large, it is better split your data into referential model, the most frequently-accessed portion of the data should go in the collection that the application loads first
  ```json
  // one person and one address
  {
     _id: "joe",
     name: "Joe Bookreader",
     address: {
              street: "123 Fake Street",
              city: "Faketon",
              state: "MA",
              zip: "12345"
              }
  }
  ```

与嵌入式文档建立一对多关系模型

  • 在设计模型方面,它也是基于与一对一相同的概念。
// one person and his multiple address
{
   "_id": "joe",
   "name": "Joe Bookreader",
   "addresses": [
               {
                  "street": "123 Fake Street",
                  "city": "Faketon",
                  "state": "MA",
                  "zip": "12345"
               },
               {
                  "street": "1 Some Other Street",
                  "city": "Boston",
                  "state": "MA",
                  "zip": "12345"
               }
            ]
}

带有参考文档的一对多关系模型

  • 在某些情况下,最好使用引用模型来获得更好的性能,如下所示。
  • 为避免重复出版商数据,请使用参考,并将出版商信息与书本分开保存。
   {
   _id: 'some string'
   name: "O'Reilly Media",
   founded: 1980,
   location: "CA",

   books: [123456789, 234567890, ...]

   }

   {
      _id: 123456789,
      title: "MongoDB: The Definitive Guide",
      author: [ "Kristina Chodorow", "Mike Dirolf" ],
      published_date: ISODate("2010-09-24"),
      pages: 216,
      language: "English"
   }

   {
      _id: 234567890,
      title: "50 Tips and Tricks for MongoDB Developer",
      author: "Kristina Chodorow",
      published_date: ISODate("2011-05-06"),
      pages: 68,
      language: "English"
   }
  • 如果将来图书阵列可能会变得很大,最好将出版商的参考文献存储在图书文档中。
  • 观察模式中的智能更改,如何在BOOK COLLECTION中将_id信息(即发布者ID)称为publisher_id
   {
   _id: "oreilly",
   name: "O'Reilly Media",
   founded: 1980,
   location: "CA"
   }

   {
      _id: 123456789,
      title: "MongoDB: The Definitive Guide",
      author: [ "Kristina Chodorow", "Mike Dirolf" ],
      published_date: ISODate("2010-09-24"),
      pages: 216,
      language: "English",

      publisher_id: "oreilly"

   }

   {
      _id: 234567890,
      title: "50 Tips and Tricks for MongoDB Developer",
      author: "Kristina Chodorow",
      published_date: ISODate("2011-05-06"),
      pages: 68,
      language: "English",

      publisher_id: "oreilly"

   }