MongoDB 提供了很多高效的数据查询工具,比如正则表达式 regular expression.
$regex

正则表达式用于匹配字符串的查询.
其语法形式有:

{ <field>: { $regex: /pattern/, $options: '<options>' } }
{ <field>: { $regex: 'pattern', $options: '<options>' } }
{ <field>: { $regex: /pattern/<options> } }

MongoDB 中,还可以采用正则表达式对象(如 /pattern/) 来指定正则表达式:

{ <field>: /pattern/<options> }

可选参数说明 - $options:

  • i - 不区分大小写
  • m - 查询匹配中使用了 anchors,例如 ^(代表开头)和 $(代表结尾),以及匹配 n 后的字符串. 没有该参数时,anchors 匹配字符串的开始或结尾.
  • x - 忽视所有空白字符. 要求 $regex 与 $option 一起用
  • s - 允许点字符 (.) 匹配所有的字符,包括换行符. 要求 $regex 与 $option 一起用.

1. 实例

假设集合 collection - products,其包含如下文档:

{ "_id" : 100, "sku" : "abc123", "description" : "Single line description." }
{ "_id" : 101, "sku" : "abc789", "description" : "First line\nSecond line" }
{ "_id" : 102, "sku" : "xyz456", "description" : "Many spaces before  line" }
{ "_id" : 103, "sku" : "xyz789", "description" : "Multiple\nline description" }

[1] - LIKE 匹配查询
匹配所有以 789 结尾sku 的文档:

db.products.find( { sku: { $regex: /789$/ } } )

类似于 SQL LIKE:

SELECT * FROM products
WHERE sku like "%789";

[2] - 不区分大小写的匹配查询
利用 option - i 实现不区分大小写的匹配查询,如匹配 ABC

db.products.find( { sku: { $regex: /^ABC/i } } )

输出如下:

{ "_id" : 100, "sku" : "abc123", "description" : "Single line description." }
{ "_id" : 101, "sku" : "abc789", "description" : "First line\nSecond line" }

[3] - 包含 S 开头的多行字符串匹配
比如以 S 开头,其中包括 /nS 开头的,利用 option - m 实现,如:

db.products.find( { description: { $regex: /^S/, $options: 'm' } } )

输出如下:

{ "_id" : 100, "sku" : "abc123", "description" : "Single line description." }
{ "_id" : 101, "sku" : "abc789", "description" : "First line\nSecond line" }

如果没有 option - m 选项,则输出如下:

{ "_id" : 100, "sku" : "abc123", "description" : "Single line description." }

如果 $regex 匹配没有 anchor,则将字符串作为整体去匹配,如:

db.products.find( { description: { $regex: /S/ } } )

则,匹配结果输出如下:

{ "_id" : 100, "sku" : "abc123", "description" : "Single line description." }
{ "_id" : 101, "sku" : "abc789", "description" : "First line\nSecond line" }

[4] - 采用 . Dot 字符的匹配查询
利用 option - s 实现 . dot 字符来匹配所有的字符,包括换行符,如:
查询 descriptionm 开头,且后面包含 line 字符串的结果:

db.products.find( { description: { $regex: /m.*line/, $options: 'si' } } )

输出如下:

{ "_id" : 102, "sku" : "xyz456", "description" : "Many spaces before     line" }
{ "_id" : 103, "sku" : "xyz789", "description" : "Multiple\nline description" }

如果没有 option - s ,则匹配结果的输入仅有如下:

{ "_id" : 102, "sku" : "xyz456", "description" : "Many spaces before     line" }

[5] - 忽略空字符的匹配
采用 option - x 来忽略空字符和注释,其中 # 表示注释, n 表示结尾,如:

var pattern = "abc #category code\n123 #item number"
db.products.find( { sku: { $regex: pattern, $options: "x" } } )

查询的匹配结果输出如下:

{ "_id" : 100, "sku" : "abc123", "description" : "Single line description." }

[6] - 数组元素使用正则表达式
在数组字段中使用正则表达式来查找内容, 对于标签的实现上非常有用.
如果要查找包含以 run 开头的sku 数据(rurunrunoob),则:

db.posts.find({sku:{$regex:"run"}})

2. pymongo 正则表达式

# --*-- coding: utf-8 --*--
from pymongo import MongoClient

client = MongoClient('192.168.1.189')
db = client['db_test']
coll = db['db_coll']

# 查询匹配开头是 abc 的 pic_name 的所有文档.
datas = coll.find({"pic_name":{"$regex": "^abc"}}) 

#模糊匹配查询 - 匹配 'SomeUser'
datas = coll.find({'$and':[{'pic_name': 'test.jpg'},{'username':{'$regex':r'(?i)SomeUser'}}]})
#模糊匹配查询 - 匹配数字
datas = coll.find({'pic_num':{'$regex':r'^[\d+]'}})

#返回指定数量的记录
count = 0
for data in coll.find().litmit(5):
    print(data)
    count += 1
    print(count)

3. 文档

[1] - MongoDB Documentation
[2] - PyMongo Tutorial

Last modification:November 3rd, 2019 at 05:19 pm