$expr
定義
バージョン 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 : NumberInt("100"), price : NumberDecimal("12") }, { _id : 2, item : "notebook", qty : NumberInt("200"), price : NumberDecimal("8") }, { _id : 3, item : "pencil", qty : NumberInt("50"), price : NumberDecimal("6") }, { _id : 4, item : "eraser", qty : NumberInt("150"), price : NumberDecimal("3") }, { _id : 5, item : "legal pad", qty : NumberInt("42"), price : NumberDecimal("10") } ] )
来月予定されているセールで、次のように価格を割引したいとします。
qty
が 100 以上の場合、割引価格はprice
の 0.5 倍になります。qty
が 100 未満の場合、割引価格はprice
の 0.75 倍になります。
割引を適用する前に、 supplies
コレクション内のどのアイテムの割引価格が 5
未満であるかを確認する必要があります。
次の例では、 $expr
と$cond
を使用して、 qty
と$lt
に基づいて割引価格を計算し、計算された割引価格がNumberDecimal("5")
より小さいドキュメントを返します。
// Aggregation expression to calculate discounted price let discountedPrice = { $cond: { if: { $gte: ["$qty", 100] }, then: { $multiply: ["$price", NumberDecimal("0.50")] }, else: { $multiply: ["$price", NumberDecimal("0.75")] } } }; // Query the supplies collection using the aggregation expression db.supplies.find( { $expr: { $lt:[ discountedPrice, NumberDecimal("5") ] } });
次の表は、各文書の割引価格と、割引価格がNumberDecimal("5")
未満であるかどうかを示しています(つまり、 ドキュメントがクエリ条件を満たしているかどうか)。
ドキュメント | Discounted Price | < NumberDecimal("5") |
---|---|---|
{"_id": 1, "item": "binder", "qty": 100, "price": NumberDecimal("12") } | NumberDecimal("6.00") | false |
{"_id": 2, "item": "notebook", "qty": 200, "price": NumberDecimal("8") } | NumberDecimal("4.00") | true |
{"_id": 3, "item": "pencil", "qty": 50, "price": NumberDecimal("6") } | NumberDecimal("4.50") | true |
{"_id": 4, "item": "eraser", "qty": 150, "price": NumberDecimal("3") } | NumberDecimal("1.50") | true |
{"_id": 5, "item": "legal pad", "qty": 42, "price": NumberDecimal("10") } | NumberDecimal("7.50") | false |
db.collection.find()
操作は、計算された割引価格がNumberDecimal("5")
未満のドキュメントを返します。
{ _id : 2, item : "notebook", qty : 200 , price : NumberDecimal("8") } { _id : 3, item : "pencil", qty : 50 , price : NumberDecimal("6") } { _id : 4, item : "eraser", qty : 150 , price : NumberDecimal("3") }
$cond
では有効な割引価格が計算されますが、その価格は返されるドキュメントには反映されません。その代わり、返されるドキュメントは、一致したドキュメントをオリジナルの状態で表現します。検索操作では、 binder
ドキュメントまたは legal pad
ドキュメントは、割引価格が 5
を超えていたため、返されませんでした。