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 の関連付けにより、モデル間の関係を作成できます。このガイドでは、参照された関連付けによって、一方のモデルが他方のモデルを参照する 2 つのモデル間の関係を作成する方法について説明します。 Mongoid は、次の参照される関連付けのタイプをサポートしています。

  • has_one

  • has_many

  • belongs_to

  • has_and_belongs_to_many

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

has_one マイクロを使用して、1 つのクラスで表されるドキュメントに、別の 子クラスによって表されるドキュメントも含まれていることを宣言できます。 次の例では、 Studioクラスに対する has_one の関係を持つ Bandクラスを作成します。

class Band
include Mongoid::Document
has_one :studio
end

has_one 関連付けを宣言する場合、子クラスは親クラスを参照する belongs_to 関連付けも使用する必要があります。 次の例では、先行する Bandクラスで参照されている Studioクラスを示しています。

class Studio
include Mongoid::Document
belongs_to :band
end

belongs_toマイクロの詳細については、「 が に属する 」セクションを参照してください。

次の例に示すように、検証を使用して、子クラスが親クラスに存在することを確認できます。

class Band
include Mongoid::Document
has_one :studio
validates_presence_of :studio
end

Mongoid の検証の詳細については、「 検証ガイド 」を参照してください。

has_many マイクロを使用して、クラスによって表されるドキュメントに、別のクラスによって表される複数の子ドキュメントが含まれていることを宣言できます。 次の例では、 Membersクラスに対する has_many の関係を持つ Bandクラスを作成します。

class Band
include Mongoid::Document
has_many :members
end

has_many 関連付けを宣言する場合、子クラスは親クラスを参照する belongs_to 関連付けも使用する必要があります。 次の例では、先行する Bandクラスで参照されている Memberクラスを示しています。

class Member
include Mongoid::Document
belongs_to :band
end

マイクロの詳細については、 [ Belongs To ]belongs_to セクションを参照してください。

次の例に示すように、検証を使用して、子クラスが親クラスに存在することを確認できます。

class Band
include Mongoid::Document
has_many :members
validates_presence_of :members
end

Mongoid の検証の詳細については、「 検証ガイド 」を参照してください。

has_many 関連付けで any? メソッドを使用すると、データベースからドキュメントセット全体を取得せずに、関連付けにドキュメントが含まれているかどうかを判断できます。

次の例では、 any? メソッドを使用して、Bandクラスのドキュメントに Members ドキュメントが含まれているかどうかを判断します。

band = Band.first
band.members.any?

次の例に示すように、any? メソッドをフィルターと併用して、指定された条件に一致するドキュメントを検索することもできます。

band = Band.first
band.members.any? { |member| member.instrument == 'piano' }

any? メソッドにクラス名を指定すると、クラスの名前で結果をフィルタリングできます。 これは多態的な 関連付けに便利です。

class Drummer < Member
end
band = Band.first
band.members.any?(Drummer)

注意

関連付けられているクラスのデータが Mongoid に読み込まれた後は、any? メソッドに対する後続の呼び出しでは、データベースはクエリされません。 代わりに、Mongoid はメモリにすでにロードされているデータを使用します。

また、exists? メソッドを呼び出して、関連付け内に永続化されたドキュメントがあるかどうかを確認することもできます。 exists? メソッドは常にデータベースをクエリし、データベースに保存されているドキュメントのみをチェックします。 exists? メソッドはフィルタリングを許可しておらず、引数を受け入れません。

次の例では、 exists? メソッドを使用して、Bandクラスに永続化された Members ドキュメントがあるかどうかを判断します。

band = Band.create!
# Member is not persisted.
band.members.build
band.members.exists?
# Outputs: false
# Persist the member
band.members.map(&:save!)
band.members.exists?
# Outputs: true

belongs_to マイクロを使用して、1 つのクラスによって表されるドキュメントが、別のクラスによって表されるドキュメントの子であることを宣言します。 デフォルトでは 、親クラスの _idフィールドは子クラスに保存されます。 次の例では、 Bandクラスへの belongs_to の関連付けを持つ Membersクラスを作成します。

class Members
include Mongoid::Document
belongs_to :band
end

次の例に示すように、optional オプションを true に設定することで、Mongoid が関連付けられている親クラスの _id を保存せずにドキュメントをデータベースに永続化できるようにします。

class Members
include Mongoid::Document
belongs_to :band, optional: true
end

Tip

アプリケーションの 構成設定 で belongs_to_required_by_default 構成オプションを false に設定することで、belongs_to 関連付けのデフォルトの動作をグローバルに変更して、親クラスを不要にすることができます。

親クラスで一致する has_one または has_many の関連付けを指定しなくても、子クラスで belongs_to の関連付けを指定できます。 そうすると、親クラスから子ドキュメントのフィールドにはアクセスできませんが、親の _idフィールドなど、子クラスに保存されている親フィールドにはアクセスできます。 次の例では、BandクラスはMembersクラスにアクセスできませんが、MembersクラスはBandクラス にアクセスできます。

class Band
include Mongoid::Document
end
class Members
include Mongoid::Document
belongs_to :band
end

明確にするために、次の例に示すように、親クラスに子クラスへの has_one または has_many の関連付けが含まれていないことを示す、inverse_of オプションを nil に設定できます。

class Band
include Mongoid::Document
end
class Members
include Mongoid::Document
belongs_to :band, inverse_of: nil
end

has_and_belongs_to_many マイクロを使用して、クラスモデルに別のクラスとの多対多の関係が含まれていることを宣言します。 多対多の関係では、1 つのクラス内の各ドキュメントを別のクラスの複数のドキュメントに関連付けることができます 。 次の例では、 Membersクラスへの has_and_belongs_to_many の関係を持つ Bandクラスを作成します。 Bandドキュメントは複数の Members ドキュメントを参照でき、Membersドキュメントは複数の Band ドキュメントを参照できます。

class Band
include Mongoid::Document
has_and_belongs_to_many :members
end
class Members
include Mongoid::Document
has_and_belongs_to_many :bands
end

has_and_belongs_to_many の関連付けを宣言すると、両方のモデル インスタンスに関連付けられているドキュメントの _id 値のリストが保存されます。 関連するドキュメントの _id 値をモデル インスタンスの 1 つだけに保存するには、inverse_of オプションを nil に設定します。 次の例では、関連付けられているドキュメントの _id 値を Bandクラスのみに保存するように Mongoid に指示します。

class Band
include Mongoid::Document
has_and_belongs_to_many :tags, inverse_of: nil
end
class Tag
include Mongoid::Document
end

Tip

has_and_belongs_to_many の関連付けがあるドキュメントを更新すると、Mongoid は更新されたドキュメントの updated_atフィールドを設定しますが、関連付けられているドキュメントの updated_atフィールドは設定しません。

集計パイプラインを使用して、参照されている関連付け全体のドキュメントをクエリできます。 集計パイプラインと、複数のコレクションにわたるクエリを作成したり、指定した形式でデータを操作したりできます。 集計パイプライン の使用方法の詳細については、 集計ガイドを参照してください。

単純なクエリの場合は、関連付けを直接クエリできます。 コレクションを直接クエリする場合、コレクション自体にあるフィールドと値のみをクエリできます。 クエリ対象に関連付けられているコレクションを直接クエリすることはできません。

例、次の Band クラスと Tour クラスについて考えてみます。

class Band
include Mongoid::Document
has_many :tours
field :name, type: String
end
class Tour
include Mongoid::Document
belongs_to :band
field :year, type: Integer
end

次の例では、 year の値が 2000 以上であるドキュメントを Tourクラスでクエリし、それらのドキュメントの band_id を保存します。 次に、それらの band_id 値を持つドキュメントを Bandクラスでクエリします。

band_ids = Tour.where(year: {'$gte' => 2000}).pluck(:band_id)
bands = Band.find(band_ids)

戻る

コールバック

項目一覧