Make the MongoDB docs better! We value your opinion. Share your feedback for a chance to win $100.
Click here >
Docs Menu
Docs Home
/ /

埋め込み関連付け

Mongoid の関連付けにより、モデル間の関係を作成できます。このガイドでは、埋め込み関連付けを使用して、同じコレクションにさまざまなタイプのドキュメントを保存する方法を学習できます。 Mongoid は次のマイクロとの埋め込み関連付けをサポートしています。

  • embeds_one

  • embeds_many

  • embedded_in

  • recursively_embeds_one

  • recursively_embeds_many

次のセクションでは、これらの関連付けタイプの使用方法について説明します。

クラスモデルに別のクラスタイプの埋め込みドキュメントが含まれていることを指定するには、親クラスの 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_onerecursively_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 は、サーバーにクエリを送信せずに埋め込み一致を実装します。

次のクエリ演算子は埋め込み一致でサポートされています。

  • 比較演算子

  • 論理演算子

  • 配列クエリ演算子

  • $exists

  • $mod

  • $type

  • $regex

  • ビット演算子

次の例では、 $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 の場合にのみオプションを指定できます。

デフォルトでは 、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 の関連付けから子ドキュメントを削除できます。

  • clear

  • delete_all

  • destroy_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

戻る

参照された関連付け

項目一覧