2016-07-01 15 views
3

埋め込みドキュメントを他のドキュメントのリファレンスとして使用することが可能かどうかを知りたいと思います。春のデータMongoDB - 他のドキュメントのリファレンスとして埋め込まれたドキュメント

私は埋め込みドキュメントを独自のコレクションに移動できますが、主な目的は埋め込みドキュメントのパフォーマンス上の利点を持ち、重複を避けることです。例えば

ユーザー

{ 
    _id: ObjectId("4fed0591d17011868cf9c982"), 
    _class: "User" 
    ... 
    addresses: [ { 
     _id: ObjectId("87KJbk87gjgjjygREewakj86"), 
     _class: "Address", 
     ... 
    } ] 
} 

注文

{ 
    _id: ObjectId("gdh60591d123487658cf9c982"), 
    _class: "Order", 
    ... 
    address: ObjectId("87KJbk87gjgjjygREewakj86") 
} 

答えて

4

あなたの場合は、典型的なのことを思い出します文書志向のDBを使い始めたときに私が犠牲にしてきた関係的アプローチです。この例のすべての エンティティが参照されていますが、冗長性はもうありません。

正規化とデータの複製を開始するという考えに慣れてください。多くの場合、参照するデータと埋め込むデータを決定することは困難です。あなたのケースはかなり明確になる傾向があります。

ドメインモデル全体を知らなくても、そのアドレスは値オブジェクトにとって最適な候補のようです。 Addressコレクションを維持しないで、ユーザーオブジェクト内に埋め込みます。 Orderでは、ユーザに参照を行うことができます。これは暗黙のうちにアドレスオブジェクトを与え、ユーザが注文するため意味があります。

しかし、私はオーダーに完全にアドレスを埋め込むことをお勧めします。まず、参照を解決する必要がないため、より高速です。第二に、出荷された注文の住所は決して変更するべきではありません!昨年のご注文を考えてみてください。住所への参照を保持すると、ユーザーが住所を変更すると、その住所に配送された情報が失われます。

提案:常にアドレスのスナップショットをとり、Orderに埋め込みます。ユーザのMongoDB IDを `Order内に通常の文字列(no @DBRef)として保存します。ユーザーが住所を変更する必要がある場合は、そのユーザーの出荷されていない注文をすべて照会し、その住所を修正することができます。

+1

あなたのコメントありがとう! –

0

私はそれをやった方法をここに掲載します何の答えを得ないため。あなたがより良い解決策を持っているなら、私はここでそれをうれしく思います。

他のコレクション内にコレクションを作成/参照する方法がないようですので、自分のコレクションにユーザーコレクションからアドレスを抽出して、hereのようにUserコレクションとOrderコレクションに参照を作成する必要がありました。私はもっ​​と柔軟なものを期待していたが、見つけられなかった。

ユーザー

{ 
    _id: ObjectId("4fed0591d17011868cf9c982"), 
    _class: "User" 
    ... 
    addresses: [ { 
     "$ref" : "addresses", 
     "$id" : ObjectId("87KJbk87gjgjjygREewakj86") 
    } ] 
} 

住所

{ 
    _id: ObjectId("87KJbk87gjgjjygREewakj86"), 
    ... 
} 

注文

{ 
    _id: ObjectId("gdh60591d123487658cf9c9867"), 
    _class: "Order", 
    ... 
    address: { 
     "$ref" : "addresses", 
     "$id" : ObjectId("87KJbk87gjgjjygREewakj86") 
    } 
} 
1

これが正しいかどうか聞いたので、私は穏やかに「いいえ」と言います。少なくとも典型的ではない。

しかし、あなたは、ユーザーからの埋め込まれたアドレスを使用して主張したいなかった場合:

あなたはOrderオブジェクト、あなたが考えるかもしれないだけではない方法で、ユーザー埋め込まれたアドレスを参照することができます! OrderにユーザーのIDを格納した場合(Order belongs_to Userの場合は既にそこにあるはずです)、アドレスインスタンスをコピーするのではなく、単にuser.addressを使用します。私はより一般的なアプローチは、デフォルトの「船として、ユーザのアドレスを使用して、新しい秩序のオブジェクトをインスタンス化することです

...ドメインをモデル化するより良いアプローチを説明することを願っています

ALTERNATIVE

「注文」のアドレスを指定しますが、必要に応じて配送先住所を上書きすることができます。理論的には、各注文はの異なる「出荷先」アドレスを持つことができます。

2つのクラスにアドレスがあるというだけで、必ずしも同じアドレスであるとは限りません。

論評

注文は変化1に対して、歴史的文書の複数です。したがって、注文は一般的にはは一度も変更されずにに変更されます。ご使用のモデルでは、ユーザーが住所を変更するたびに住所が変更されます。その変更は注文に波及し、通常の注文ビジネスロジックがある限り間違っています。

去年のご住所がスペインにあり、昨年のご注文レポートを実行したときに注文番号1がスペインになったとします。あなたの今年のアドレスがポルトガルで、注文番号1が同じレポートにポルトガルを示しているとします。それは事実上間違っているでしょう。

BTW:@Mattは、「問題のドメイン」の観点から、あなたが持っているようにそれをモデル化したくないというヒントを教えてくれました。私はそれについて詳しく説明しています...

関連する問題