mongodb默认使用隐式and关系,多个字段条件直接写在同一对象中;同一字段的多个独立条件或需控制求值顺序时必须显式使用$and;数组多值匹配默认为or,跨元素匹配无需$elemmatch,单元素内多条件才需$elemmatch。

MongoDB 默认就是 AND 关系,多个条件写在同一个对象里就行,不需要显式写 $and —— 除非你要对同一字段做多个独立判断,或者需要控制求值顺序。
多个字段同时匹配(隐式 AND)
比如查 status 是 "active" 且 score 大于 80 的文档,直接写:
{ "status": "active", "score": { "$gt": 80 } }
这等价于 SQL 的 WHERE status = 'active' AND score > 80。MongoDB 驱动或 shell 里用 find() 传入这个对象即可。
- 多个键并列在同一层对象中,就是 AND
- 不支持用逗号分隔多个条件对象(如
{a:1}, {b:2}),会报错或只取第一个 - 如果某个字段要同时满足多个独立条件(比如
score既要大于 80 又要小于 100),必须用$and显式包裹
同一字段多个条件必须用 $and
例如查 score 在 80 到 95 之间的文档,不能写成 {"score": {"$gt": 80, "$lt": 95}} —— 这其实是合法的,但容易和“字段存在且值是对象”混淆;更明确、更通用的做法是:
{ "$and": [ { "score": { "$gt": 80 } }, { "score": { "$lt": 95 } } ] }
尤其当条件涉及不同类型操作符(比如 $in 和 $regex 混用)时,$and 能避免歧义。
-
$and的每个子条件必须是独立对象,不能合并成一个 - 多数情况下,用单个对象里的多条件(如
{"score": {"$gt": 80, "$lt": 95}})更简洁,但注意它只适用于同一字段的范围类操作 - 驱动层面(如 Node.js 的 mongodb driver)对
$and支持稳定,但某些旧版 Compass 或 Atlas 查询界面可能不自动展开嵌套逻辑,建议优先测试
混合 AND 和 OR 的真实写法
想查 “状态是 active 且 (类型是 user 或 admin)” 的文档,不能靠缩进或顺序,必须用 $or 套在 $and 里,或反过来:
{ "status": "active", "$or": [ { "role": "user" }, { "role": "admin" } ] }
这是最常用也最安全的写法。MongoDB 不允许把 $or 直接和普通字段键平级混写而不加外层结构。
-
$or数组里的每个元素必须是完整条件对象,不能只写{"role": "user"}以外的部分 - 不要试图用 JavaScript 逻辑(如
||)在查询里拼条件——服务端不执行 JS 表达式 - 如果
$or分支很多,注意 BSON 文档大小上限(16MB),单个查询别塞几十个分支
数组字段里的多条件:别漏掉 $elemMatch
查数组字段 tags 中**同时包含** "urgent" 和 "backend" 的文档,不能写 {"tags": "urgent", "tags": "backend"} —— 后者会被覆盖,实际只剩一个键。
正确做法是用 $elemMatch:
{ "tags": { "$elemMatch": { "$eq": "urgent", "$eq": "backend" } } }
但这语法本身不合法($eq 不能重复),真正要表达“一个元素等于 urgent 且另一个元素等于 backend”,就得拆开:
{ "tags": "urgent", "tags": "backend" }
等等——不对,这还是错的。实际上 MongoDB 对数组的多值匹配默认是 OR:只要数组里有 "urgent",又有 "backend"(哪怕在不同元素里),就命中。真要要求**同一个数组元素**满足多个条件(比如 comments 里某条评论既 rating > 4 又 author = "alice"),才必须用 $elemMatch:
{ "comments": { "$elemMatch": { "rating": { "$gt": 4 }, "author": "alice" } } }
- 没用
$elemMatch时,数组字段的多个条件是跨元素 OR 关系 - 用了
$elemMatch,才表示“至少一个数组元素同时满足所有子条件” - 点号访问(如
"comments.0.author")只能查固定索引,不适用于动态匹配
最容易被忽略的是:数组字段的多条件语义取决于你到底想匹配“整个数组具备多个值”,还是“某个数组元素具备多个属性”。前者不用 $elemMatch,后者必须用——但很多人凭直觉反着写,结果查不到数据。











