$and$andでは論理的なAND演算を 1 つ以上の式(<expression1>や<expression2>など)の配列で実行し、すべての式を満たすドキュメントを選択します。注意
MongoDB では、カンマで区切られた式のリストを指定するときには暗黙的な
AND操作になります。
互換性
次の環境でホストされる配置には $and を使用できます。
MongoDB Atlas はクラウドでの MongoDB 配置のためのフルマネージド サービスです
MongoDB Enterprise: サブスクリプションベースの自己管理型 MongoDB バージョン
MongoDB Community: ソースが利用可能で、無料で使用できる自己管理型の MongoDB のバージョン
構文
$andの構文は次のとおりです。
{ $and: [ { <expression1> }, { <expression2> } , ... , { <expressionN> } ] }
動作
MongoDB のクエリ オプティマイザでは、$and 式の句を評価する際に、実行に最適なプランを選択するために、$and 式の句を満たすのにどのインデックスを役立てることができるのかが検討されます。
クエリ エンジンでクエリが最適化されるよう、$and はエラーを次のように処理します。
$andに指定した式が単独で評価されるとエラーが発生する場合、その式を含む$andでエラーが発生することがありますが、必ずしもエラーが発生するわけではありません。$andに最初に指定した式の後に式を指定すると、最初の式がfalseと評価されていてもエラーが発生することがあります。
たとえば、次のクエリでは、 $x が 0 の場合、常にエラーが発生します。
db.example.find( { $expr: { $eq: [ { $divide: [ 1, "$x" ] }, 3 ] } } )
$and に複数の式を指定した次のクエリでは、$x が 0 であるドキュメントがある場合にエラーが発生することがあります。
db.example.find( { $and: [ { x: { $ne: 0 } }, { $expr: { $eq: [ { $divide: [ 1, "$x" ] }, 3 ] } } ] } )
MongoDB Shell (mongosh)を含む、ほとんどのプログラミング言語とドライバーは、同じオブジェクトレベルで重複するキーを持つオブジェクトの構築を許可していません。例えば、次のクエリを考慮してください。
db.inventory.find( { price: { $in: [ 7.99, 3.99 ], $in: [ 4.99, 1.99 ] } } )
上記のクエリは、フィールド名 price に同じオブジェクトレベルで重複する演算子があるため、正しく構成されません。その結果、サーバーに送信されるクエリは意図したものとは異なります。クエリが期待通りに動作するためには、明示的な AND 演算子を使用してください:
db.inventory.find( { $and: [ { price: { $in: [ 7.99, 3.99 ] } }, { price: { $in: [ 4.99, 1.99 ] } } ] } )
このクエリは、両方の条件が満たされていることを明示的にチェックします。price 配列には、各 $in セットから少なくとも1つの値が含まれている必要があります。このようなシナリオの対処方法の詳細については、例セクションをご覧ください。
例
同じフィールドを指定する複数の式を含む $and クエリ
次のクエリを考えてみましょう。
db.inventory.find( { $and: [ { price: { $ne: 1.99 } }, { price: { $exists: true } } ] } )
クエリは、次の条件を満たす inventory コレクション内のすべてのドキュメントを選択します。
priceフィールドの値が1.99と等しくない、かつpriceフィールドが存在する。
このクエリを簡素化するには、price フィールドの演算子式を、暗黙的にネストされた AND を持つ単一のクエリオブジェクトに統合します:
db.inventory.find( { price: { $ne: 1.99, $exists: true } } )
同じフィールドで重複する条件を扱う場合、特にこのような書き換えが不可能な場合があります。以下がその例です。
db.inventory.find( { status: { $ne: "closed", $ne: "archived" } } )
上記のクエリは、同じオブジェクトレベルの同じ status フィールド名で $ne 演算子を複数回使用するため、正しく構築されません。この場合、$nin 演算子はより効果的な解決策を提供します:
db.inventory.find( { status: { $nin: [ "closed", "archived" ] } } )
クエリの書き換え方法は、ユースケースの意図するセマンティクスに依存します。次のクエリを考えてみましょう。
db.inventory.find( { $and: [ { status: "new" }, { status: "processing" } ] } )
status が new または processing であるドキュメントを検索するには、$in 演算子を使用できます。
db.inventory.find( { status: { $in: [ "new", "processing" ] } } )
status フィールドが配列 [ "new", "processing" ] であり、ドキュメントに new と processing の両方の値が含まれているかどうかを確認したい場合は、$all 演算子を使用します。
db.inventory.find( { status: { $all: [ "new", "processing" ] } } )
この文脈では、このクエリは意味的にはAND と同等ですが、配列フィールドをクエリする場合は $all がより明確であることがよくあります。
フィールド名の重複と同様に、クエリで使用される演算子の重複にも同様の考慮が適用されます。