多身份验证用户帐户的MongoDB模式设计

多身份验证用户帐户的MongoDB模式设计,mongodb,express,mongoose,passport.js,Mongodb,Express,Mongoose,Passport.js,我即将构建node.js/express/mongoose/passport应用程序,我正在考虑为用户和帐户设计合适的模式 将有用户从twitter和facebook以及本地帐户登录。在以后的阶段,我希望用户能够将twitter和facebook与我的应用程序(甚至更多的外部帐户)连接起来。 我想不出解决这种情况的好办法。以下是我正在考虑的选项: 1.有档案模型和账户模型。配置文件文档表示唯一用户,而帐户提供用户名和密码(内部帐户)或来自身份验证提供程序(外部帐户)的身份验证数据。配置文件必须至

我即将构建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
});
我不喜欢的是,不同的帐户数据导致的帐户文档不太一致,而且当我的用户登录时,我很难找到正确的帐户(在嵌套文档中搜索UID和帐户类型-。-)

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

var ProfileSchema = new Schema({
    firstname: String,
    lastname: String,
    email: String,        
    twitter-uid: String,
    facebook-uid: String
    password: String
});
这太难看了-找到正确的帐户数据可能更容易/更快,但维护起来并不好

有更好的解决办法吗是否有最佳实践?

1)在MongoDB中构建数据结构时,您可以采取三种策略:

  • a) 嵌入文档数组
  • b) 嵌入引用数组
  • c) 展开到父文档中
策略(a)是您描述的第一个策略,其中概要文件文档包含一系列帐户子文档

策略(b)与策略(a)类似,但您将使用对其他文档(通常在帐户集合中)的引用数组,而不是嵌入实际文档

策略(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语法):


有了适当的索引,这个查询会非常快。

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

MongoDB中的模式设计和数据建模

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

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

    • 嵌入式数据建模:
      • are具有单一文档结构,被称为非规范化模型
      • 支持文档级原子操作
      • 易于执行的积垢
      • 70%的情况下使用,读操作性能高
      • 大小很容易达到其阈值,即16MB,并且容易出现高冗余
      • 在一对一和一对多关系中推荐
    • 引用或链接数据建模
      • 模仿SQL数据库的规范化表以减少数据重复和冗余
      • reference或_id用于引用另一个文档,类似于使用主键和外键连接SQL中的表
      • 在30%的情况下使用
      • 在多对多关系中推荐
数据建模的前景
  • 概念数据建模:关于功能和服务的大图,其中还包括
    • ER数据建模:数据库设计的图形化方法
    • 模式设计
  • 逻辑数据建模:概念数据建模将使用编程语言、表格等转换为逻辑数据建模(程序)(服务器代码)
  • 物理数据建模:在用户插入实际数据的情况下,将逻辑数据管理付诸实践。(数据库)
数据模型的类型
  • 平面、星形、层次、关系、对象关系
为文档之间的关系建模
  • 通常,您应该构造模式,以便应用程序在一次读取操作中接收所有必需的信息
与嵌入文档建立一对一关系模型 与嵌入文档建立一对多关系模型
  • 在设计模型方面,它也基于与一对一相同的概念
与参考文档建立一对多关系模型
  • 在某些情况下,最好使用参考模型以获得更好的性能,如下所示
  • 为避免出版商数据重复,请使用参考资料,并将出版商信息与图书集分开存放
  • 如果未来books数组可能会变得巨大,那么最好将publisher引用存储在book文档中
  • 观察模式中的智能变化,了解
    \u id
    信息(即出版商id)在藏书中如何被称为
    出版商id

与关系数据库不同,MongoDB的最佳模式设计在很大程度上取决于如何访问数据。您将使用帐户数据做什么?您将如何访问它?我将使用帐户数据与passport进行身份验证。配置文件数据将访问几乎每一页的多功能用途。我将通过mongoose访问它,ODMSo帐户数据只有在用户登录时才会被访问,而一旦发生这种情况,您将使用会话机制来跟踪登录情况?(与每页访问都需要帐户数据相反)我需要每页的用户数据。但我不知道该怎么做
 db.profile.find( 
        { email: 'fred.rogers@example.com', 'accounts.kind': 'facebook' }
        );
  - 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"
   }
   {
   _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"

   }