如何在 MongoDB 中执行模糊查询(类似 SQL 的 LIKE)?
在 MongoDB 中,实现类似 SQL LIKE 的模糊查询,主要使用 正则表达式(Regular Expression) 操作符 $regex。
以下是几种常见的场景及其对应的 MongoDB 写法:
1. 基础模糊查询 (包含字符串)
SQL:
sql
SELECT * FROM users WHERE name LIKE '%john%';
MongoDB (Shell / 驱动):
javascript
// 写法一:直接使用正则对象 (最常用)
db.users.find({ name: /john/ });
// 写法二:使用 $regex 操作符
db.users.find({ name: { $regex: 'john' } });
2. 不区分大小写 (Case Insensitive)
SQL:
sql
/* MySQL */
SELECT * FROM users WHERE name LIKE '%john%'; /* 默认通常不区分,取决于 collation */
/* PostgreSQL */
SELECT * FROM users WHERE name ILIKE '%john%';
MongoDB:
使用 $options: 'i' 选项。
javascript
// 写法一:正则对象
db.users.find({ name: /john/i });
// 写法二:$regex 操作符
db.users.find({
name: {
$regex: 'john',
$options: 'i'
}
});
3. 以某字符串开头 (Starts With) - 推荐
SQL:
sql
SELECT * FROM users WHERE name LIKE 'john%';
MongoDB:
使用正则的 ^ 符号。
javascript
db.users.find({ name: /^john/ });
性能提示: 这种查询(前缀查询)如果字段上有索引,MongoDB 可以 利用索引,查询速度非常快。
4. 以某字符串结尾 (Ends With)
SQL:
sql
SELECT * FROM users WHERE name LIKE '%john';
MongoDB:
使用正则的 $ 符号。
javascript
db.users.find({ name: /john$/ });
5. 在 Node.js (Mongoose) 中使用变量
如果你是在代码中使用变量进行查询,不能直接写 /variable/,需要动态构建正则对象。
javascript
const keyword = "john";
// 方法 1:使用 JavaScript RegExp 对象
// 注意:如果 keyword 包含特殊字符(如 . * ?),需要先进行转义处理
db.users.find({
name: new RegExp(keyword, 'i') // 'i' 表示不区分大小写
});
// 方法 2:Mongoose 语法
User.find({
name: { $regex: keyword, $options: 'i' }
});
⚠️ 性能警告与优化方案
虽然 $regex 很方便,但在大数据量下有严重的性能陷阱:
全表扫描 (Full Collection Scan):
- 查询
/john/(包含) 或/john$/(以...结尾) 无法有效利用标准索引。 - MongoDB 必须扫描集合中的每一条文档来匹配正则表达式。如果数据量达到几十万或上百万,查询会非常慢。
- 查询
前缀查询优化:
- 只有
/^john/(以...开头) 这种形式,且该字段建立了索引,查询才会快。
- 只有
如果你的数据量很大,且需要高性能的全文搜索,建议使用以下替代方案:
- 方案 A: MongoDB 文本索引 ($text)
- 适用于简单的关键词搜索(分词匹配,而非子串匹配)。
- 建立索引:
db.users.createIndex({ name: "text" }) - 查询:
db.users.find({ $text: { $search: "john" } })
- 方案 B: Atlas Search (推荐)
- 如果你使用的是 MongoDB Atlas 云服务,可以使用内置的 Atlas Search (基于 Lucene),它支持高性能的模糊搜索、拼写纠错等。
- 方案 C: Elasticsearch
- 将数据同步到 Elasticsearch 进行专业的搜索处理。