$and$and对由一个或多个表达式(<expression1>、<expression2>等)组成的数组执行逻辑AND操作,并选择满足所有表达式的文档。注意
指定用逗号分隔的表达式列表时,MongoDB 提供隐式
AND操作。
兼容性
可以使用 $and 查找托管在以下环境中的部署:
MongoDB Atlas:用于云中 MongoDB 部署的完全托管服务
MongoDB Enterprise:基于订阅、自我管理的 MongoDB 版本
MongoDB Community:源代码可用、免费使用且可自行管理的 MongoDB 版本
语法
$and 采用以下语法:
{ $and: [ { <expression1> }, { <expression2> } , ... , { <expressionN> } ] }
行为
在评估 $and 表达式中的子句时,MongoDB 的查询优化器会考虑哪些可用索引在选择要执行的最佳计划时有助于满足 $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 值集中的一个值。如需了解如何处理此类情况的更多信息,请参阅示例部分。
示例
使用指定同一字段的多个表达式的 $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 通常更为清晰。
与重复字段名称类似,相同的注意事项也适用于查询中使用的重复操作符。