2011-11-19 41 views
11

のは、私のような文書のコレクションがあるとしましょう:NoSQLデータベース(MongoDB)に外部キーを適用する方法は?

{ "_id" : 0 , "owner":0 "name":"Doc1"},{ "_id" : 1 , "owner":1, "name":"Doc1"}, etc 

を、他方では所有者が別のコレクションとして表されます:私は確信したときに、ことを確認するにはどうすればよい

{ "_id" : 0 , "username":"John"}, { "_id" : 1 , "username":"Sam"} 

私は正しい方法でユーザーを参照する文書を挿入します。旧式のRDBMSでは、これは外部キーを使用して簡単に行うことができます。

ビジネスコードからの挿入の正当性を確認できますが、攻撃者がサーバーに自分の要求を改ざんして「所有者」を入れた場合、100となり、Mongoは例外を戻しません。

この状況を実際のアプリケーションでどのように処理する必要があるのか​​を知りたいと思います。

ありがとうございます!

+1

攻撃者があなたのリクエストを改ざんする可能性がある場合、応答する例外を改ざんできなかったと思いますか? – deed02392

答えて

12

MongoDBには(おそらく気付いたように)外部キーはありません。したがって、基本的には、「ユーザーがリクエストを改ざんしないようにしてください。アプリケーションが参照整合性ルールに従うデータのみを挿入できるようにしてください。

MongoDBは多くの点で優れていますが、外部キーが必要な場合は、おそらく問題の正しい解決策ではありません。

13

MongoDBはクライアント側での外部キー関係の処理を奨励していますが、「データベース参照」の考え方も提供しています。this help pageを参照してください。

つまり、DBRefを使用することはお勧めできません。クライアントコードが関連付けを管理するようにするか、最初から文書をまとめて(より良い方法で)リンクさせることができます。所有者の "ドキュメント"を所有者オブジェクト自体の中に埋め込むことを検討することができます。あなたの使用パターンに合うように文書をアセンブルし、MongoDBが輝きます。

+0

+1この問題を回避するための再構成方法に関するヒント。 – deed02392

0

ユーザー名が一意の場合は、_idとして使用することをお勧めします。インデックスに保存します。保存されているドキュメントでは、ドキュメントが作成されたときに、アプリケーションの 'owner'の値を 'username'の値として設定し、他のコードで決してそれを更新させないでください。

オーナーを変更する必要がある場合は、ビジネスルールを実装した適切なAPIを提供してください。

外部キーは必要ありません。

+1

これを行う場合を除き、ユーザーがユーザー名を変更したい場合は、既存のレコードを削除して、変更されたユーザー名で新しいレコードを挿入する必要があります。 –

0

誰かが本当にProject/WebAppで外部キーを強制したい場合。次に、MixSQLのアプローチ、つまりSQL + NoSQLを使用する必要があります。

大量の参照がないBulkyデータをNoSQLデータベースストアに格納することをお勧めします。 Like:ホテルや場所のデータタイプ。

しかし、OAuthモジュールのテーブル、TokenStore、UserDetails、UserRole(マッピングテーブル)などのような深刻なものがある場合は、SQLを使用できます。

0

NoSQLソリューションとして、MariaDB(NewSQL) をSQLとNoSQLの組み合わせで使用し、MySQL開発者が優れたパフォーマンスで実装できます。

0

これは1対1の関係です。別々のコレクションを維持するのではなく、1つのドキュメントを別のドキュメントに埋め込む方がよいでしょう。 hereに、mongodbでモデル化する方法とそのメリットを確認してください。

ドキュメントでは明示的に言及されていませんが、埋め込みは外部キー制約と同じ効果をもたらします。このアイデアを明確にしたいだけです。

C1:

{ "_id" : 0 , "owner":0 "name":"Doc1"},{ "_id" : 1 , "owner":1, "name":"Doc1"}, etc 

C2:

{ "_id" : 0 , "username":"John"}, { "_id" : 1 , "username":"Sam"} 

そして、あなたはC1._idを参照するためにC2._idに外部キー制約を宣言した場合(MongoDBのがそれを可能にすると仮定して)あなたはそのような2つのコレクションを持っている場合これは、に文書を挿入できないことを意味します。C2._idは存在しません。C1です。埋め込まれた文書とこれを比較する:

{ 
    "_id" : 0 , 
    "owner" : 0, 
    "name" : "Doc1", 
    "owner_details" : { 
     "username" : "John" 
    } 
} 

今owner_detailsフィールドはC2コレクションからデータを表し、残りのフィールドはC1からのデータを表します。存在しないドキュメントにowner_detailsフィールドを追加することはできません。あなたは基本的に同じ効果を達成しています。

関連する問題