0

Document と author コレクションがあるとします。次の 2 つの方法で設計できます。

最初の方法:

documents
{_id:1, title:"document 1", author:"John", age: 34}
{_id:2, title: "document 2", author: "Maria", age:42 }
{_id:3, title: "document 3", author: "John", age: 34}

authors
{_id:1, name:"John", age:34}
{_id:2, name:"Maria", age:42}

2 番目の方法:

documents
{_id:1, title:"document 1", id_author:1}
{_id:2, title: "document 2", id_author: 2}
{_id:3, title: "document 3", id_author: 1}

authors
{_id:1, name:"John", age:34}
{_id:2, name:"Maria", age:42}

ドキュメントを取得するときに結合をシミュレートする必要がないため、最初の方法は適切です。ドキュメント コレクションにすべてのデータがあります。しかし一方で、マリアの年齢を変更する必要がある場合は、両方のコレクションで行う必要があります。

2番目の方法は逆です。ドキュメントとその作成者の年齢が必要な場合は、最初にドキュメントをクエリし、次に作成者をクエリする必要があります。しかし良いことは、Maria の年齢を変更しなければならないときに、著者のコレクションで変更するだけでよいということです。

それで、どの解決策がより良いですか?著者コレクションに必要なフィールドが多いほど、2 番目の方法を使用する可能性が高くなると思います。しかし、最初の方法を使用している場合、両方のコレクションでマリアの年齢を更新するために使用できる単一のクエリはありますか?

最も使用されているソリューションはどれですか?

4

3 に答える 3

2

複数のコレクションでの更新はトランザクションになります。MongoDB はトランザクションをサポートしていません。

どちらの方法にもそれぞれ欠点があります。

作成者データを含む最初の方法は、その内容が変更される可能性がないロギング状況でより適切な場合があります。

2 番目の方法は、作成者の詳細が時間の経過とともに変化または増加すると予想される場合 (ほとんどの場合) に適しています。

すでに述べたように、ドキュメントをそれぞれの作成者のドキュメントに埋め込むことは、2 つの提案の利点を組み合わせる方法ですが、長期的には問題を引き起こす可能性があります。

于 2013-02-07T10:12:57.090 に答える
1

最初の方法の問題は更新です。

{_id:1, title:"document 1", author:"John", age: 34}

実際には、そこに作成者IDと、クエリに必要な詳細の一部(スキーマの冗長性)が必要になると想像できます。

お気づきのように、これは問題を引き起こす可能性があります。

しかし、その一方で、マリアの年齢を変更する必要がある場合は、両方のコレクションで変更する必要があります。

年齢は少なくとも年に一度は変わりますが、年齢が間違っている場合はもっと頻繁に変わります。名前も変更される可能性があります。特に、後でこの「ジョン」に姓が付いているか、彼の名前が実際には「ジョニー」であることがわかった場合はそうです。

したがって、ここで冗長性を作成する際の問題は、作成者のドキュメントが大幅に変更され、非常にパフォーマンスの低い更新を実行する必要が生じ、ワーキングセットが大幅に増加する可能性があることです。これがどのくらいの頻度で発生するかについては、提供された情報では言えませんが、それはあなたが決めることです。

通常、冗長性を作成する良い方法は、現在のドキュメントの別のドキュメントで非常にまれに更新される属性が必要な場合です。ここではそうではないようです。

2番目の方法は通常、この種のランダムに読み取られ更新された関係を実行するデフォルトの方法ですが、3番目の方法である埋め込みも考えられます。

ドキュメントを作成者に埋め込むことができます。MongoDBの最大ドキュメントサイズは16Megであるため、これは保存しようとしているドキュメントの数によって異なります。

可能性があると言われていることは次のとおりです。

{
    _id: {},
    name: 'John',
    age: 43,
    documents: [
        { id: 1, title: "New Document" }
    ]
}

$pullこれの1つの欠点は、またはなどのメモリ内操作の使用です$pushが、ドキュメントが一貫して大幅に成長している場合は、断片化が見られる可能性があります。

しかし、繰り返しになりますが、これらはあなたが取り入れるべき単なるメモであり、実際には提供されていない情報に依存します。

于 2013-02-07T10:07:13.013 に答える
1

両方のアプローチを組み合わせることをお勧めします。「静的」情報はドキュメントコレクションとともに保存され、変数データは作成者コレクションに一元化されます。変数データを取得する必要がある場合にのみ、作成者IDを使用します。彼の年齢を取得します。このようなもの:

documents
{_id:"1", title:"document 1", author:"John", authorId: "1"}
{_id:"2", title: "document 2", author: "Maria", authorId: "2"}
{_id:"3", title: "document 3", author: "John", authorId: "1"}

authors
{_id:"1", name:"John", age:34}
{_id:"2", name:"Maria", age:42}

年齢はあまり頻繁に必要とされないものですが、頻繁に更新される可能性があるため、両方の状況をより適切に処理できます。

他の誰かが述べたように、Mongoはトランザクションではなく、作成者とドキュメントを一度に作成すると問題が発生する可能性があります。

于 2013-02-07T17:09:36.820 に答える