定義
バージョン 5.0 での変更。
$exprクエリ言語の中で 集計式を使用できます。
互換性
次の環境でホストされる配置には $expr を使用できます。
MongoDB Atlas はクラウドでの MongoDB 配置のためのフルマネージド サービスです
MongoDB Enterprise: サブスクリプションベースの自己管理型 MongoDB バージョン
MongoDB Community: ソースが利用可能で、無料で使用できる自己管理型の MongoDB のバージョン
構文
$expr の構文は次のとおりです。
{ $expr: { <expression> } }
引数には、あらゆる有効な集計式となる可能性があります。 詳細については、「式 」を参照してください。
動作
$exprは、 $matchステージの同じドキュメントのフィールドを比較するクエリ式を作成できます。
$matchステージが$lookupステージの一部である場合、 $exprはlet変数を使用してフィールドを比較できます。 例については「 $lookupを使用して複数の結合と相関サブクエリを実行する 」を参照してください。
$expr演算子に配置されている$eq 、 $lt 、 $lte 、 $gt 、および$gte比較演算子は、 $lookupステージで参照されるfromコレクションのインデックスを使用できます。 制限:
インデックスはフィールドと定数の比較にのみ使用できるため、
letオペランドは定数に変換する必要があります。たとえば、
$aと定数値の比較にはインデックスを使用できますが、$aと$bの比較には使用できません。letオペランドが空の値または欠損値に変換される場合の比較には、インデックスは使用されません。
例
1 つのドキュメントの 2 つのフィールドの比較
以下のドキュメントを持つmonthlyBudgetコレクションを考えてみましょう。
db.monthlyBudget.insertMany( [ { _id : 1, category : "food", budget : 400, spent : 450 }, { _id : 2, category : "drinks", budget : 100, spent : 150 }, { _id : 3, category : "clothes", budget : 100, spent : 50 }, { _id : 4, category : "misc", budget : 500, spent : 300 }, { _id : 5, category : "travel", budget : 200, spent : 650 } ] )
次の操作では、 $exprを使用して、 spentの量がbudgetを超えるドキュメントを検索します。
db.monthlyBudget.find( { $expr: { $gt: [ $spent , $budget ] } } )
この操作は次の結果を返します。
{ _id : 1, category : "food", budget : 400, spent : 450 } { _id : 2, category : "drinks", budget : 100, spent : 150 } { _id : 5, category : "travel", budget : 200, spent : 650 }
$expr条件文で を使用する
一部のクエリでは、クエリフィルターを定義するときに条件ロジックを実行する能力が必要です。 集計パイプラインには、条件ステートメントを$cond Expressするための 演算子が用意されています。$exprを$cond演算子とともに使用することで、クエリ ステートメントに条件付きフィルターを指定できます。
次のドキュメントを使用してサンプルsupplies コレクションを作成します。
db.supplies.insertMany( [ { _id : 1, item : "binder", qty : Int32("100"), price : Decimal128("12") }, { _id : 2, item : "notebook", qty : Int32("200"), price : Decimal128("8") }, { _id : 3, item : "pencil", qty : Int32("50"), price : Decimal128("6") }, { _id : 4, item : "eraser", qty : Int32("150"), price : Decimal128("3") }, { _id : 5, item : "legal pad", qty : Int32("42"), price : Decimal128("10") } ] )
来月予定されているセールで、次のように価格を割引したいとします。
qtyが 100 以上の場合、割引価格はpriceの 0.5 倍になります。qtyが 100 未満の場合、割引価格はpriceの 0.75 倍になります。
割引を適用する前に、 supplies コレクション内のどのアイテムの割引価格が 5 未満であるかを確認する必要があります。
次の例では、 $exprと$condを使用して、 qtyと$ltに基づいて割引価格を計算し、計算された割引価格がDecimal128("5")より小さいドキュメントを返します。
// Aggregation expression to calculate discounted price let discountedPrice = { $cond: { if: { $gte: ["$qty", 100] }, then: { $multiply: ["$price", Decimal128("0.50")] }, else: { $multiply: ["$price", Decimal128("0.75")] } } }; // Query the supplies collection using the aggregation expression db.supplies.find( { $expr: { $lt:[ discountedPrice, Decimal128("5") ] } });
次の表は、各文書の割引価格と、割引価格がDecimal128("5")未満であるかどうかを示しています(つまり、 ドキュメントがクエリ条件を満たしているかどうか)。
ドキュメント | Discounted Price | < Decimal128("5") |
|---|---|---|
{"_id": 1, "item": "binder", "qty": 100, "price": Decimal128("12") } | Decimal128("6.00") |
|
{"_id": 2, "item": "notebook", "qty": 200, "price": Decimal128("8") } | Decimal128("4.00") |
|
{"_id": 3, "item": "pencil", "qty": 50, "price": Decimal128("6") } | Decimal128("4.50") |
|
{"_id": 4, "item": "eraser", "qty": 150, "price": Decimal128("3") } | Decimal128("1.50") |
|
{"_id": 5, "item": "legal pad", "qty": 42, "price": Decimal128("10") } | Decimal128("7.50") |
|
db.collection.find()操作は、計算された割引価格がDecimal128("5")未満のドキュメントを返します。
{ _id : 2, item : "notebook", qty : 200 , price : Decimal128("8") } { _id : 3, item : "pencil", qty : 50 , price : Decimal128("6") } { _id : 4, item : "eraser", qty : 150 , price : Decimal128("3") }
$condでは有効な割引価格が計算されますが、その価格は返されるドキュメントには反映されません。その代わり、返されるドキュメントは、一致したドキュメントをオリジナルの状態で表現します。検索操作では、 binder ドキュメントまたは legal pad ドキュメントは、割引価格が 5を超えていたため、返されませんでした。