Overview
Mongoid の関連付けにより、モデル間の関係を作成できます。このガイドでは、埋め込み関連付けを使用して、同じコレクションにさまざまなタイプのドキュメントを保存する方法を学習できます。 Mongoid は次のマイクロとの埋め込み関連付けをサポートしています。
embeds_oneembeds_manyembedded_inrecursively_embeds_onerecursively_embeds_many
次のセクションでは、これらの関連付けタイプの使用方法について説明します。
埋め込み 1
クラスモデルに別のクラスタイプの埋め込みドキュメントが含まれていることを指定するには、親クラスの embeds_one マイクロと 埋め込みクラスの embedded_in マイクロを使用します。 次の例では、埋め込まれた Labelクラスを持つ Bandクラスを作成しています。
class Band include Mongoid::Document embeds_one :label end class Label include Mongoid::Document field :name, type: String embedded_in :band end
Mongoid は、親ドキュメントの embeds_one マイクロで埋め込まれたドキュメントを、埋め込みクラスと同じ名前のフィールドとして保存します。 前述の Label ドキュメントは、次の例に示すように、 Bandドキュメントに保存されています。
# Band document { "_id" : ObjectId("..."), "label" : { "_id" : ObjectId("..."), "name" : "Periphery", } }
次の例に示すように、store_as オプションを使用して、埋め込みドキュメントを別の名前で保存することができます。
class Band include Mongoid::Document embeds_one :label, store_as: "record_label" end
埋め込みが多い
クラスモデルに異なるクラスタイプの複数の埋め込みドキュメントが含まれていることを指定するには、親クラスの embeds_many 構造と 埋め込みクラスの embedded_in マイクロを使用します。 次の例では、複数の埋め込まれた Album 型ドキュメントを含む Bandクラスを作成しています。
class Band include Mongoid::Document embeds_many :albums end class Album include Mongoid::Document field :name, type: String embedded_in :band end
Mongoid は、親ドキュメントに embeds_many マイクロで埋め込まれたドキュメントを、埋め込みクラスと同じ名前の配列フィールドとして保存します。 前述の Album ドキュメントは、次の例に示すように、 Bandドキュメントに保存されています。
{ "_id" : ObjectId("..."), "albums" : [ { "_id" : ObjectId("..."), "name" : "Omega", } ] }
次の例に示すように、store_as オプションを使用して、埋め込みドキュメントを別の名前で保存することができます。
class Band include Mongoid::Document embeds_many :albums, store_as: "records" end
再帰埋め込み
recursively_embeds_one と recursively_embeds_many マイクロを使用して、同じタイプの 1 つ以上のドキュメントを親クラスに埋め込むことができます。 どちらのドキュメントも、parent_* メソッドと child_* メソッドを介して親ドキュメントと子ドキュメントにアクセスできます。ここで、* はクラスの名前を表します 。 次の例では、複数のバンド名を表すために他の複数の Band ドキュメントを再帰的に埋め込む Bandクラスを作成します。
class Band include Mongoid::Document field :name, type: String recursively_embeds_many end
次の例に示すように、parent_band メソッドと child_band メソッドを介して親ドキュメントと子ドキュメントにアクセスできます。
root = Band.new(name: "Linkin Park") # Add child bands child_one = root.child_band.build(name: "Lincoln Park") child_two = root.child_band.build(name: "Xero") # Access parent band child_one.parent_band # Outputs: root
埋め込み関連付けのクエリ
ドット表記を使用して親クラスのコレクションをクエリするときに、埋め込みドキュメントにアクセスできます。
次の例では、ドット表記を使用して、Bandクラスに埋め込まれている Tour 型のドキュメントをクエリします。 クエリでは、tours.year の値が 2000 以上であるドキュメントが返されます。
Band.where('tours.year' => {'$gte' => 2000})
次の例に示すように、pluckプロジェクションメソッドを使用すると、関連付けられている親ドキュメントを取得せずに埋め込みドキュメントを取得できます。
# Get awards for bands that have toured since 2000 Band.where('tours.year' => {'$gte' => 2000}).pluck(:awards)
Mongoid クエリ メソッドを使用して 埋め込み一致 を実行できます。これにより、アプリケーションにすでにロードされているドキュメントの埋め込み関連付けに対してクエリを実行できます。Mongoid は、サーバーにクエリを送信せずに埋め込み一致を実装します。
次のクエリ演算子は埋め込み一致でサポートされています。
次の例では、 $gte 比較演算子を使用して、ロードされた Bandドキュメントの埋め込み toursフィールドをクエリします。
band = Band.where(name: 'Astral Projection').first tours = band.tours.where(year: {'$gte' => 2000})
ロードされたドキュメントでの埋め込み一致には、次の既知の制限があります。
次の機能では、埋め込み一致は実装されていません。
JavaScriptコードを実行する演算子( $where など)
$expr や $jsonSchema などの他のサーバー機能に実装される演算子
Mongoid は、
$gteと$lte条件を使用して、Range引数をハッシュに展開します。 これにより、場合によっては無効なクエリが発生し、InvalidQuery例外が発生します。$regex演算子では、$optionsフィールドにオプションも提供しながら、正規式オブジェクトをパターンとして指定することはできません。 正規式パターンが string の場合にのみオプションを指定できます。
_id フィールドの省略
デフォルトでは 、Mongoid は埋め込みドキュメントに _idフィールドを追加します。 このフィールドは、モデルで _idフィールドを明示的に指定し、デフォルト値を省略することで、埋め込みドキュメントから省略できます。 次の例ではMongoid に Albumsクラスに _idフィールドを追加しないように指示します。
class Album include Mongoid::Document field :name, type: String field :_id, type: Object embedded_in :band end
前述の Albumsクラスでは、_idフィールドは自動的に追加されません。 デフォルト値がない場合、モデルでデフォルト値を指定しない限り、Mongoid はデータベースに値を保存しません。
埋め込み関連付けの削除
次のいずれかの方法を使用して、embeds_many の関連付けから子ドキュメントを削除できます。
cleardelete_alldestroy_all
clearメソッドは $unset 演算子を使用して、親ドキュメントから埋め込み関連付け全体を削除します。clear メソッドは destroy コールバックを実行しません。 次の例では、 clear メソッドを使用して、Bandクラスからすべての埋め込み関連付けを削除します。
band = Band.find(...) band.tours.clear
delete_allメソッドは $pullAll 演算子を使用して、埋め込み関連付け内のドキュメントを削除します。delete_all は、関連付けがまだ読み込まれていない場合はその関連付けを読み込み、アプリケーションに存在するドキュメントのみを削除します。 delete_all メソッドは destroy コールバックを実行しません。 次の例では、 delete_all メソッドを使用して、Bandクラスからすべての埋め込み Album ドキュメントを削除します。
band = Band.find(...) band.tours.delete_all
destroy_allメソッドでは、埋め込み関連付け内のドキュメントを削除するために、 $pullAll 演算子も使用されます。また、関連するドキュメントに定義されている destroy コールバックも実行します。 次の例では、 destroy_all メソッドを使用して、Bandクラスからすべての埋め込み Album ドキュメントを削除します。
band = Band.find(...) band.tours.destroy_all