Overview
このガイドでは、Mongoid がクエリから結果を返す方法をカスタマイズする方法を学習できます。 MongoDB、次のアクションを実行して結果の表示方法を変更できます。
サンプル データ
このガイドの例では、バンドまたはステージを表す Band モデルを使用します。 Band モデルの定義は、異なるクエリ機能を示すために、各セクションで異なる場合があります。 一部のセクションでは、特定のバンドを管理するユーザーを表す Manager モデルや、特定のバンドによるライブ パフォーマンスを表す Tour モデルも使用します。
指定されたフィールドを返す
MongoDBでは、プロジェクションとは、結果に含めるフィールドまたは除外するフィールドを指定するプロセスです。Mongoid は、フィールドをプロジェクトために次の演算子を提供します。
only: 含めるフィールドを指定しますwithout: 除外するフィールドを指定します
含めるフィールドの指定
only メソッドは、データベースから指定されたフィールドのみを検索します。
次のコードでは、membersフィールドの値が 4 であるドキュメントから nameフィールドのみが返されます。
Band.where(members: 4).only(:name)
注意
_id フィールド
MongoDBでは、明示的に含めない場合でも _idフィールドは結果に含まれます。
ロードされていない属性を参照しようとすると、Mongoid は Mongoid::Errors::AttributeNotLoaded エラーを発生させます。
また、 only メソッドを使用して、埋め込みドキュメントのフィールドを含めることもできます。
Band モデルには複数の Tour オブジェクトが埋め込まれている ことを考えてみましょう。 次のコードに示すように、year などの Tour モデルからフィールドをプロジェクトできます。
bands = Band.only(:name, 'tours.year')
次に、返されたドキュメントから埋め込みフィールドにアクセスできます。
# Returns the first Tour object from # the first Band in the results bands.first.tours.first
参照された関連付けのフィールドを only メソッドに渡すことはできますが、埋め込みオブジェクトをロードするときにプロジェクションは無視されます。 Mongoid は、参照先の関連付けのすべてのフィールドをロードします。 例、前述のコードに示すように、埋め込み Tourオブジェクトにアクセスすると、Mongoid は yearフィールドだけでなく、完全なオブジェクトを返します。
注意
MongoDB 4.4 以降を実行中配置に接続している場合、同じクエリで関連付けとそのプロジェクションのフィールドを指定することはできません。
ドキュメントに has_one または has_and_belongs_to_many の関連付けが含まれており、only メソッドを呼び出すときに Mongoid がそれらの関連付けをロードする場合は、属性のリストに外部キーを持つフィールドを含める必要があります。
次の例では、Band モデルと Manager モデルに has_and_belongs_to_many の関連付けがあります。
class Band include Mongoid::Document field :name, type: String has_and_belongs_to_many :managers end class Manager include Mongoid::Document has_and_belongs_to_many :bands end
次のコードは、manager_idsフィールドを含める場合に Mongoid が関連する Manager オブジェクトをロードする方法を示しています。
# Returns null Band.where(name: 'Astral Projection').only(:name).first.managers # Returns the first Manager object Band.where(name: 'Astral Projection').only(:name, :manager_ids).first.managers
フィールドの除外
without メソッドを使用して、結果からフィールドを明示的に除外できます。
次のコードでは、返される Band オブジェクトから yearフィールドが除外されます。
Band.where(members: 4).without(:year)
重要
_id フィールド
Mongoid ではさまざまな操作に_id フィールドが必要になるため、結果から _idフィールドまたはid エイリアスを除外することはできません。without メソッドに _id または id を渡すと、Mongoid はそれを無視します。
結果を並べ替える
Mongoid がドキュメントを返す順序を指定するには、order メソッドと order_by メソッドを使用します。
これらのメソッドは、ドキュメントをどのフィールドで並べ替えるか、および各フィールドに対して昇順または降順のどちらを使用するかを示すハッシュを受け入れます。
整数、記号、または string を使用してソート方向を指定できます。 整合性を高めるために、アプリケーション全体で同じソート構文を使用することをお勧めします。 次のリストは、それぞれの構文と、name フィールドと year フィールドで並べ替える方法を示しています。
整数
1(昇順)と-1(降順)例:
Band.order(name: 1, year: -1)
記号
:ascと:desc例:
Band.order(name: :asc, year: :desc)
String
"asc"と"desc"例:
Band.order_by(name: "asc", year: "desc")
order メソッドは次の並べ替え指定も受け入れています。
2 つの要素からなる配列の配列:
文字列
例:
Band.order([['name', 'asc'], ['year', 'desc']])
記号
例:
Band.order([[:name, :asc], [:year, :desc]])
ascシンボルの メソッドとdescメソッド例:
Band.order(:name.asc, :year.desc)
SQL構文
例:
Band.order('name asc', 'year desc')
Tip
order または order_by を使用する代わりに、asc メソッドと desc メソッドを使用して並べ替え順序を指定することもできます。
Band.asc('name').desc('year')
ソート指定を連鎖させる場合、最初の呼び出しは最初のソート順序を定義し、最後の呼び出しは前のソートが適用された後の最後のソート順序を定義します。
結果のページ分割
Mongoid は、Criteria オブジェクトで使用できる limit、skip、batch_size のページ区切りメソッドを提供します。 次のセクションでは、これらの演算子の使用方法について説明します。
結果数の制限
Mongoid が返す結果の数を制限するには、limit メソッドを使用します。
次のコードは、最大 5 ドキュメントを検索します。
Band.limit(5)
注意
あるいは、take メソッドを使用して、データベースから指定した数のドキュメントを検索することもできます。
Band.take(5)
結果をスキップする
skip メソッドまたはそのエイリアス offset を使用すると、指定した数の結果をスキップできます。
skip への limit 呼び出しを連鎖させると、次の例に示すように、ドキュメントがスキップされた後に制限が適用されます。
Band.skip(2).limit(5) # Skips the first two results and returns # the following five results
次のコードは、結果を返すときに最初の 3 ドキュメントをスキップします。
Band.skip(3) # Equivalent Band.offset(3)
結果のバッチの生成
大規模なクエリを実行する場合、およびCriteria#each などの列挙メソッドを使用してクエリ結果を反復処理する場合、Mongoid は自動的にMongoDB getMore コマンド を使用して結果をバッチで読み込みます。デフォルトのバッチするサイズは 1000 ですが、batch_size メソッドを使用して別の値を設定できます。
次のコードを使用することで、バッチするサイズが 500 に設定されます。
Band.batch_size(500)
より負荷の高い関連付け
関連付けを含むドキュメントをクエリする場合、早期ロードにより、関連するドキュメントを後で遅延してロードするのではなく、関連するドキュメントを基本ドキュメントと同時にロードすることができます。これにより、データベースクエリの数が減り、関連付けが多いワークロードのパフォーマンスが向上します。Mongoid は、関連付けがあるドキュメントをクエリするときに、関連するドキュメントを早期ロードするための 2 つの方法を提供します(includes と eager_load)。
include メソッド
includes メソッドは、関連付けごとに個別のクエリを使用して関連付けを読み込みます。次のコードでは、バンドとそれに関連するデータベースとラベルを個別のクエリを使用して読み込みます。
Band.where(name: 'The Beatles').includes({ albums: :songs }, :labels).first
includes メソッドを使用すると、Mongoid は基本クラスに対してクエリを実行してすべての基本ドキュメントを取得し、その後に早期ロードする関連付けごとに個別のクエリを実行します。
前の例では、次のクエリが実行されます。
Bandドキュメントを検索するための 1 回のクエリ関連する
Albumドキュメントを読み込む 1 つのクエリ関連する
Labelドキュメントを読み込む 1 つのクエリ関連する
Songドキュメントを読み込む 1 つのクエリ
concern_load メソッド
eager_load メソッドは、 MongoDB集計パイプラインを$lookup 演算子とともに使用して、1 回のクエリですべての関連付けを読み込みます。次のコードでは、単一の集計パイプラインクエリを使用して、バンドとそれに関連するデータベースとラベルを読み込みます。関連付けごとに $lookup ステージが含まれます。
Band.where(name: 'The Beatles').eager_load({ albums: :songs }, :labels).first
パフォーマンスに関する考慮事項
includes メソッドと eager_load メソッドはどちらも早期読み込みを実行しますが、その方法は異なります。includes メソッドは基本ドキュメントに対して 1 つのクエリを実行し、その後 関連付けごとに個別のクエリを実行します。eager_load メソッドは、関連付けをロードするために、$lookup ステージを持つ単一の集計パイプラインを使用します。
eager_load メソッドは、includes よりもクエリを実行し、使用するメモリが少なくなります。ただし、メソッドの効率は、ドキュメント内の関連付けのタイプによって異なります。
eager_loadは、has_many、has_and_belongs_to_many、およびほとんどのデータセットで複数の関連付けの読み込みで高速ですincludesは、belongs_to、has_one、およびほとんどのデータセットでネストされた関連付けで高速です
ユースケースと関連付けのタイプに最適な方法を選択します。
Return Raw Data
raw メソッドをクエリに連結することで、モデル インスタンスを作成しなくても、結果を未加工のハッシュとして返すことができます。
次のコードでは、クエリ結果を未加工のハッシュとして検索します。
Band.where(country: 'Argentina').raw
デフォルトでは 、raw メソッドは Mongoid がデータベースからドキュメントを受け取った時点で正確にドキュメントを返します。オプションで、raw メソッドで typed オプションを true に設定することで、結果ハッシュ内のフィールドをモデルフィールド宣言の型にキャストできます。
Band.where(country: 'Argentina').raw(typed: true)
未加工の結果を返すクエリを実行し、後でこれらの結果をモデルに変換したい場合は、結果に対して raw(false) を呼び出せます。
# Retrieves raw results results = Band.where(members: 4).raw # ... Perform actions on results # Returns instantiated model objects from raw results bands = results.raw(false).to_a
詳細情報
クエリ結果を変更するために Criteria オブジェクトで使用できるメソッドの完全なカタログについては、APIドキュメントの Mongoid::Criteria::Queryable モジュール参照を参照してください。
クエリの構築の詳細については、「ドキュメント クエリの指定」ガイドを参照してください。