38

node.js/express/ mongoose / passportアプリケーションを構築しようとしています。ユーザーとアカウントの適切なスキーマ設計について考えています。

ネイティブ アカウントだけでなく、Twitter や Facebook からもログインするユーザーがいます。後の段階で、ユーザーが twitter と facebook の両方をアプリケーション (さらにはさらに多くの外部アカウント) に接続することを望んでいます。

その状況の良い解決策が思い浮かびません。私が考えているオプションは次のとおりです。

1.プロファイルモデルとアカウントモデルを持つ。プロファイル ドキュメントは一意のユーザーを表し、アカウントはユーザー名とパスワード (内部アカウント) または認証プロバイダーからの認証データ (外部アカウント) のいずれかを提供します。プロファイルには、ネストされたアカウント ドキュメントが少なくとも 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
});

うーん、これは醜いです -.- 適切なアカウント データを見つけるのは簡単/高速かもしれませんが、維持するのは良くありません。

より良い解決策はありますか?ベストプラクティスはありますか?

4

2 に答える 2

61

1) MongoDB でデータを構造化するには、次の 3 つの方法があります。

  • a) 埋め込みドキュメントの配列
  • b) 埋め込み参照の配列
  • c) 親ドキュメントに展開

戦略 (a) は、最初に記述したもので、プロファイル ドキュメントにアカウント サブドキュメントの配列が含まれています。

戦略 (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' }
        );

適切なインデックスを使用すると、このクエリは非常に高速になります。

于 2012-06-21T22:10:44.063 に答える
3

あなたのような同じようなニーズを持つ人の助けになれば幸いです。

MongoDB でのスキーマ設計とデータ モデリング

  • SQLには固定/厳密なスキーマがありますが、NoSQLには動的/柔軟なスキーマがあります。つまり、ドキュメント構造を強制しません

  • MongoDB には 2 種類のデータ モデルがあります。

    • 埋め込みデータ モデリング:
      • は単一のドキュメント構造を持ち、非正規化モデルと呼ばれます
      • ドキュメント レベルのアトミック操作をサポートします。
      • 簡単に CRUD を実行できます
      • ケースの 70% で使用され、読み取り操作のパフォーマンスが高い
      • サイズは簡単にしきい値の 16 MB に達し、冗長性が高くなる傾向があります
      • 1 対 1 および 1 対多の関係で推奨
    • 参照またはリンクされたデータ モデリング:
      • SQL データベースの正規化されたテーブルを模倣して、データの重複と冗長性を減らします。
      • reference または _id は、主キーと外部キーを使用して SQL でテーブルを結合するのと同様に、別のドキュメントを参照するために使用されます。
      • ケースの 30% で使用されます。
      • 多対多の関係で推奨

データ モデリングの視点

  • 概念データ モデリング: 機能とサービスに関する全体像。
    • ER データ モデリング: データベース設計へのグラフィカルなアプローチ。
    • スキーマ設計
  • 論理データ モデリング: 概念的なデータ モデリングは、プログラミング言語、テーブルなどを使用して論理データ モデリング (プログラム) に変換されます (サーバー コード)。
  • 物理データ モデリング: ユーザーが実際のデータを挿入する論理的 DM を実践する (データベース)。

データ モデルの種類

  • フラット、スター、階層、リレーショナル、オブジェクト リレーショナル

ドキュメント間のモデル関係

  • 一般に、アプリケーションが 1 回の読み取り操作で必要なすべての情報を受け取るように、スキーマを構築する必要があります。

埋め込みドキュメントを使用して 1 対 1 の関係をモデル化する

  - 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"
              }
  }
  ```

埋め込みドキュメントを使用して 1 対多の関係をモデル化する

  • また、モデルの設計に関しても、1 対 1 と同じコンセプトに基づいています。
// 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"
               }
            ]
}

参照ドキュメントを使用して 1 対多の関係をモデル化する

  • 場合によっては、以下のようにパフォーマンスを向上させるために参照モデルを使用することをお勧めします。
  • 出版社データの重複を避けるには、参照を使用し、書籍コレクションとは別のコレクションに出版社情報を保管してください。
   {
   _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"
   }
  • 将来、books 配列が巨大になる可能性がある場合は、出版社の参照を book ドキュメント内に格納することをお勧めします。
  • _idBOOK COLLECTION で情報 (つまり、出版社 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"

   }
于 2020-07-20T08:38:42.307 に答える