MongoDB条件查询:从简单到复杂的查询示例

在MongoDB中,条件查询是从集合中筛选数据的核心操作。通过指定不同的条件,我们可以精确地获取符合需求的文档。本文将从简单到复杂,用具体示例讲解MongoDB的条件查询方法,适合初学者快速上手。

一、准备示例数据

为了方便演示,我们假设有一个名为users的集合,包含以下文档(可理解为用户信息表):

{
  "_id": 1,
  "name": "Alice",
  "age": 25,
  "hobbies": ["reading", "hiking"],
  "address": { "city": "Beijing", "country": "China" }
},
{
  "_id": 2,
  "name": "Bob",
  "age": 30,
  "hobbies": ["gaming", "coding"],
  "address": { "city": "Shanghai", "country": "China" }
},
{
  "_id": 3,
  "name": "Charlie",
  "age": 22,
  "hobbies": ["music", "sports"],
  "address": { "city": "Guangzhou", "country": "China" }
},
{
  "_id": 4,
  "name": "David",
  "age": 35,
  "hobbies": ["travel", "photography"],
  "address": { "city": "Chengdu", "country": "China" }
}

二、基础条件查询(最简单的“等于”条件)

MongoDB中,条件查询通过find()方法实现,条件以“键值对”的形式写在查询文档中。最基础的条件是等于,即查询某个字段等于指定值的文档。

示例1:查询年龄为25的用户

db.users.find({ age: 25 })
  • 解释{ age: 25 }是查询条件,表示“年龄字段等于25”。
  • 结果:返回_id为1的文档(Alice的信息)。

示例2:查询城市为“Shanghai”的用户

db.users.find({ "address.city": "Shanghai" })
  • 解释address.city是嵌套字段的点表示法(address是父文档,city是子字段),表示查询地址中城市为“Shanghai”的文档。
  • 结果:返回_id为2的文档(Bob的信息)。

三、比较运算符(大于、小于、不等于等)

MongoDB支持多种比较运算符,用于更灵活的条件筛选,常见的有:
- $gt:大于(greater than)
- $lt:小于(less than)
- $gte:大于等于(greater than or equal)
- $lte:小于等于(less than or equal)
- $ne:不等于(not equal)

示例3:查询年龄大于25岁的用户

db.users.find({ age: { $gt: 25 } })
  • 解释{ age: { $gt: 25 } }表示“年龄字段大于25”。
  • 结果:返回_id为2(Bob,30岁)、4(David,35岁)的文档。

示例4:查询年龄在22到30岁之间的用户(含22和30)

db.users.find({ age: { $gte: 22, $lte: 30 } })
  • 解释:条件是一个对象,包含$gte(大于等于)和$lte(小于等于),表示年龄范围在22到30之间。
  • 结果:返回_id为1(25岁)、2(30岁)、3(22岁)的文档。

示例5:查询姓名不等于“Bob”的用户

db.users.find({ name: { $ne: "Bob" } })
  • 解释$ne表示“不等于”,即排除姓名为“Bob”的文档。
  • 结果:返回_id为1、3、4的文档。

四、逻辑运算符(AND、OR、NOT)

当需要组合多个条件时,MongoDB提供了逻辑运算符$and$or$not

示例6:查询年龄大于25且城市为“China”的用户(AND条件)

db.users.find({ 
  age: { $gt: 25 }, 
  "address.country": "China" 
})
  • 解释:多个条件直接写在查询文档中,MongoDB默认是AND关系,即同时满足“年龄>25”和“国家是China”。
  • 结果:返回_id为2(Bob,30岁,中国)、4(David,35岁,中国)的文档。

示例7:查询年龄25岁或城市为“Beijing”的用户(OR条件)

db.users.find({ 
  $or: [
    { age: 25 }, 
    { "address.city": "Beijing" }
  ] 
})
  • 解释$or需要将条件放在数组中,每个元素是一个条件对象,满足任意一个条件即可。
  • 结果:返回_id为1(Alice,25岁)、1(Beijing)的文档。

示例8:查询年龄不大于30且爱好不含“gaming”的用户(NOT条件)

db.users.find({ 
  age: { $not: { $gt: 30 } }, // 年龄≤30
  hobbies: { $ne: "gaming" }  // 爱好不等于gaming
})
  • 解释$not用于否定条件,这里否定$gt:30(即年龄≤30),同时排除爱好含“gaming”的用户。
  • 结果:返回_id为1(Alice,25岁,爱好不含gaming)、3(Charlie,22岁,爱好不含gaming)的文档。

五、数组查询(处理数组字段)

如果文档包含数组类型(如hobbies),MongoDB支持数组相关的条件查询,常见场景包括:
- 数组包含某个元素
- 数组长度等于指定值
- 数组中元素满足特定条件

示例9:查询爱好包含“reading”的用户

db.users.find({ hobbies: "reading" })
  • 解释:直接写数组元素作为条件,MongoDB默认会匹配数组中包含该元素的文档(相当于$in操作)。
  • 结果:返回_id为1(Alice,爱好含reading)的文档。

示例10:查询爱好包含“reading”或“travel”的用户

db.users.find({ hobbies: { $in: ["reading", "travel"] } })
  • 解释$in用于指定一个值列表,只要数组包含列表中的任意一个元素即可匹配。
  • 结果:返回_id为1(Alice,含reading)、4(David,含travel)的文档。

示例11:查询爱好数组长度为2的用户

db.users.find({ hobbies: { $size: 2 } })
  • 解释$size用于指定数组长度,这里表示数组元素个数为2。
  • 结果:返回_id为1(Alice,2个爱好)、2(Bob,2个爱好)的文档。

六、字符串匹配查询(正则表达式)

使用$regex可以对字符串进行模糊匹配,支持正则表达式语法。

示例12:查询姓名以“A”开头的用户

db.users.find({ name: { $regex: /^A/ } })
  • 解释/^A/是正则表达式,表示“以A开头”,$regex用于指定匹配规则。
  • 结果:返回_id为1(Alice)的文档。

示例13:查询姓名包含“li”且不区分大小写的用户

db.users.find({ name: { $regex: /li/i } })
  • 解释/li/i中的i表示不区分大小写,li表示匹配包含“li”的字符串。
  • 结果:若有姓名为“Alex”或“Li”的用户会被匹配,此处示例数据中无符合条件的用户。

七、总结

MongoDB条件查询通过组合不同的条件运算符和逻辑运算符,可以实现从简单到复杂的筛选需求。核心关键点:
1. 基础查询:直接通过字段名=值匹配(等于条件)。
2. 比较运算符$gt/$lt等处理范围查询。
3. 逻辑运算符$and(默认)、$or$not组合多条件。
4. 数组查询$in$size等处理数组元素匹配。
5. 字符串匹配$regex支持正则表达式模糊查询。

通过练习上述示例,你可以逐步掌握MongoDB条件查询的核心逻辑,应对大部分数据筛选场景。

练习题

尝试用以下条件查询,验证你的理解:
1. 查询年龄小于30岁且城市为“Guangzhou”的用户。
2. 查询爱好包含“coding”或“photography”的用户。
3. 查询姓名以“C”开头且年龄为偶数的用户。

(答案可在MongoDB客户端中执行对应查询语句验证)

Xiaoye