涉及什么零件

  • 编程语言:Python
  • 网络框架:Flask
  • 数据库:PyMongo + MongoDB Atlas

起步

开启 Atlas 全文搜索支持

参考 Tutorial: Create and Query an Atlas Search Index - MongoDB Documentation 在自己的 Atlas - 对应数据库 里面开启全文搜索功能。

其中,在 Configure Search Index 对话框里面,本例配置如下:

  • Name 一栏填:example

  • 下面那个代码框填:

1
2
3
4
5
6
7
8
9
10
{
"mappings": {
"fields": {
"title": {
"analyzer": "lucene.cjk",
"type": "string"
}
}
}
}

其中 lucene.cjk 是用于中文(也包括日文韩文之类)的全文搜索索引引擎。

PyMongo

主要用到 .aggregate() 方法

设变量 db 为数据库 Client 实例,即:

1
db = pymongo.MongoClient(MONGO_URI, connect = False)[DATABASE][COLLECTION]

规定:全文搜索的关键字记作变量 keyword,结果应该只从某一特定分类 category 里面取(即结果的 category 值需要等于变量 category)。

设置筛选条件,记为变量 pipeline

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
pipeline = [
{
'$search': {
'index': 'example',
'text': {
'query': keyword,
'path': 'title'
}
}
},
{
'$sort': {
'id': -1
}
},
'$match': {
'category': category
}
]

上面条件的意思是:利用 example 索引器(主要指定了索引引擎等),在每个条目的 title 属性里面找有没有包含 keyword 的(全文搜索步),结果按照 id 属性倒序排列,结果的 category 属性应与给定变量 category 的值一致。

然后

1
cursors = db.aggregate(pipeline)

结果是一个 pymongo.command_cursor.CommandCursor 类型的对象实例,需要对其作 list() 操作:

1
objs = list(cursors)

进阶

计数

参考了 MongoDB Aggregation: How to get total records count? - StackOverflow

记住:$facet 字段应丢在 pipeline 的末尾。

1
2
3
4
5
6
7
8
pipeline.append({
'$facet': {
'paginatedResults': [{ '$skip': (page-1)*per_page }, { '$limit': per_page }],
'totalCount': [
{ '$count': 'count' }
]
}
})

返回值(经过 list() 后),记为 result

1
2
3
4
5
6
[{
'paginatatedResults': [{}, {}, ..., {}],
'totalCount': [{
'count': 100
}]
}]

result[0]['totalCount'][0]['count'] 即可得到结果条目总数。