6

文字列の所有者 (文字列ごとに 1 人以上の所有者) と共に文字列をデータベースに格納しています。

私は常に、従来のリレーショナル データベースである MySQL を使用してきました。その場合、文字列を一意の ID とともに 1 つのテーブルに格納し、文字列の一意の ID を (複数のレコードとして) 所有者と共に 2 番目のテーブルに格納します。

次に、SQL Join を使用して所有者ごとに文字列をフェッチできます。

私は現在、MongoDB を使用するプロジェクトに取り組んでおり、上記と同じことを行っています。

NoSQL データベースを扱う場合、これは間違った方法と見なされますか? NoSQL を扱うとき、「関係」の観点から考えるべきではありませんか?

MongoDB で同じことを達成するために考えられる別の方法は、次のように保存することです。

{
    "string": "foobar",
    "owners": [
        "owner1",
        "owner2",
        "owner3"
    ]
}

ただし、この場合、「owner1 が所有するすべての文字列」を検索する方法がわかりません。

4

4 に答える 4

6

NoSQL データベースを扱う場合、これは間違った方法と見なされますか? NoSQL を扱うとき、「関係」の観点から考えるべきではありませんか?

埋め込みの場合には非常に多くの質問がありますが、それはごくわずかです。

埋め込みを希望する場合は、ここで言及されていないことを考慮する必要があります。

  • ドキュメントのサイズは大幅に増加しますか? その場合、ドキュメントはディスク上で頻繁に移動する可能性があります。これは悪いことです。
  • 関連する行には、作業中のコレクションへの多数の結合がありますか (つまりvideo、埋め込みできませんuser)。この場合、冗長データを関連行からサブ文書にコピーする際、特にその冗長データを更新する際に問題が発生する可能性があります。
  • これらの結果をどのように表示する必要がありますか?

結果を表示することは、常に埋め込むかどうかの重要な決定要因です。多数の行 (たとえば 1000 行) をページ分割する必要がある場合は$slice、通常のクエリまたは集計フレームワークで演算子を使用する必要があります。1000 では非常に高速かもしれませんが、遅かれ早かれ、メモリ内操作は通常のクエリよりも遅くなります (実際には常にそうあるべきです)。

サブドキュメントの複雑な並べ替えと表示が必要な場合は、これらを分割して、代わりに次のドキュメント構造にすることができます。

{
    "string": "foobar",
    "owners": [
        ObjectId(),
        ObjectId(),
        ObjectId()
    ]
}

コレクション内の行のownerように聞こえるので、これは実際にはデータにとってよりパフォーマンスの高い構造であると思います。userusers

ユーザーのデータを変更する可能性があるサブドキュメントを作成する代わりに、それらの_id. リレーションシップを埋め込むことができるので、これは非常に優れていますが、同時にドキュメントはほとんど大きくなりません。これは、ディスクが常に移動する可能性が低いことを意味します。それだけでなく、ワーキング セットが小さいため、全体的によりパフォーマンスの高い操作が作成されます。それだけでなく_id、所有者が変更されることはめったにないため、このデータのサブセットに対して実行する必要がある可能性が最も高い操作は、作成と削除だけです。

複雑なソートとページネーションに戻ります。もちろん、このデータを使用するownerと、1 回の往復ですべての ID を取得できます。次に、別の往復で、必要な複雑な表示を可能にするusers通常のクエリを使用して、テーブル内の所有者の行をクエリできます。$in

したがって、この構造全体が非常にパフォーマンスが高いことがわかりました。

もちろん、この構造はクエリに依存します。代わりにユーザーに文字列 id を格納する方が良いかもしれませんが、この場合、ユーザーはおそらく多くの文字列を所有できるため、そうではありません。紐側に埋め込まれた関係。

うまくいけば、これが役に立ち、私はぐるぐる回っていませんが、

于 2012-12-20T08:34:40.090 に答える
5

dbasemanの答えを補完するために:

はい、あなたのアプローチは大丈夫のようです。「owner1が所有するすべての文字列」を簡単に検索できます

db.collection.find({owners: 'author1'})

これが可能なのは、mongodbが配列を特別な方法で処理するためです。

于 2012-06-24T12:02:28.010 に答える
3

埋め込まれたデータを扱うときは、mongoのAtomicityの動作に慣れることをお勧めします。良い出発点はここにあります:http: //docs.mongodb.org/manual/core/data-modeling/#atomicity

ユーザーObjectId(Sammayeが推奨)を「owners」配列に追加/削除する特定のケースでは、文字列ドキュメントでfindAndModify()操作を使用して、そのドキュメントに多くの書き込みが行われるようにします。発生しても、データの整合性は維持されます。

この操作では、次の演算子を使用することをお勧めします。

  1. 所有者を追加するときは、重複を防ぐために$addToSetを使用します
  2. 所有者を削除する場合、$ pull

両方ともここに文書化されています:http: //docs.mongodb.org/manual/reference/operators/#update-operators-array

于 2012-12-24T11:55:36.450 に答える
2

これは正しいアプローチのように見えます。ただし、それは常にプロジェクトの全体性、目標(パフォーマンス、柔軟性)、最も頻繁に実行するクエリ、アドホッククエリを実行する必要があるかどうか、およびその他の要因に依存することを忘れないでください。ただし、一般的には、あなたが書いたように、ネストされたドキュメントを使用することは、結合と外部キーを使用する代わりの正しい方法です。

最大ドキュメントサイズ(現在は16MB)も覚えておいてください。これは、特定の文字列の所有者が多数(たとえば、数十万)いる場合に問題になります。

于 2012-06-24T05:52:39.553 に答える