引言
Whoosh 是什么?
Whoosh 是一个用纯 Python 编写的全文搜索库,设计初衷是为 Python 应用提供快速、灵活和高效的搜索功能。与其他搜索引擎不同,Whoosh 完全基于python实现,不依赖于外部服务或平台,因此非常适合嵌入到各种 Python 项目中。
Whoosh 的应用场景
- 日志文件分析:Whoosh 可以用来搜索和分析日志文件,帮助系统管理员快速定位问题或异常。
- 搜索引擎:Whoosh 可以用来构建简单的搜索引擎,帮助用户在大量文档中快速找到所需信息。
- 内容管理系统:在内容管理系统中,Whoosh 可以用来索引文章、博客帖子或其他内容,以便用户能够搜索相关内容。
为什么选择 Whoosh?
- 纯 Python 实现:无需其他依赖,易于安装和使用。
- 灵活性:可以根据需求定制索引和搜索行为。
- 易于集成:适用于各种 Python 项目和框架。
- 高效性:尽管是纯 Python 实现,但性能表现优异,足以满足大多数应用需求。
安装
环境要求
Whoosh 兼容 Python 3.x,并且没有其他特定的系统要求。
安装 Whoosh
可以通过 pip 安装 Whoosh:
bash
pip install Whoosh
创建和管理索引
定义 Schema并建立索引目录
Schema 定义了索引的结构,包括字段名称和类型。以下是一个简单的 Schema 定义:
python
from whoosh.index import create_in
from whoosh.fields import Schema, TEXT, ID
schema = Schema(title=TEXT(stored=True), path=ID(stored=True), content=TEXT)
index_dir='index'
ix = create_in(index_dir, schema)
我的理解就是相当于数据库的建表操作
其中stored用于指明是否存储该项的具体值
- 如果为
True
可以再搜索结果中直接访问到这个字段 - 如果为
False
的话就只能进行搜索,但是在结果中是无法直接访问具体内容的。
原因是倒排索引本身只会建立词元到记录之间的映射关系,并不会保存记录本身。要显示保存记录才能在搜索结果中访问
添加文档到索引
添加文档到索引非常简单,只需使用 IndexWriter
对象:
python
from whoosh.index import open_dir
ix = open_dir(index_dir)
writer = ix.writer()
writer.add_document(title=u"My Document", path=u"/a", content=u"This is the content of my document.")
writer.commit()
打开索引,然后获取writer,使用writer对象的add_document
方法添加记录,最后使用commit
方法确认提交。
whoosh会自动的进行词法分析并据此建立词元到记录之间的索引关系。
更新和删除文档
更新文档与添加文档类似,可以先删除旧文档,再添加新文档:
python
# 删除文档
writer.delete_by_term('path', u'/a')
# 添加更新后的文档
writer.add_document(title=u"Updated Document", path=u"/a", content=u"Updated content.")
writer.commit()
搜索功能
基本搜索语法
使用 Searcher
对象进行搜索,实现了上下文管理器:
python
from whoosh.qparser import QueryParser
with ix.searcher() as searcher:
# 这一句分成两部分理解:
# 1、根据schema和查询字段生成一个查询解析器
# 2、使用查询解析器解析查询语句并生成查询对象
query = QueryParser("content", ix.schema).parse(u"document")
results = searcher.search(query)
for result in results:
print(result['title'])
这种方法只能在单个字段上查询,比如根据时间查询,根据作者查询等等
高级搜索功能
Whoosh 支持多种高级搜索功能,如布尔查询、通配符查询和范围查询:
python
from whoosh.qparser import MultifieldParser
query = MultifieldParser(["title", "content"], ix.schema).parse(u"title:document AND content:updated")
results = searcher.search(query)
ps:就不细说了,我做日志分析也用不到这么多
处理搜索结果
搜索结果包含多个匹配的文档,可以通过遍历 results
对象来处理每个结果:
python
for result in results:
print(result['title'], result['path'])
分析器和过滤器
使用
Whoosh 提供了多种分析器和过滤器,可以根据需要进行定制:
python
from whoosh.analysis import StemmingAnalyzer
analyzer = StemmingAnalyzer()
schema = Schema(title=TEXT(stored=True, analyzer=analyzer), content=TEXT(analyzer=analyzer))
注意
就是在划分词元的时候用什么分词器来划分,划分会影响索引的效果
比如:
- 有一个文档的内容是:我爱中国
- 分词器1划分:[我,爱,中国]
- 分词器2划分:[我爱,中国]
那么此时我们搜索我
,基于分词器2构建的索引是检索不到的
如果使用分词器2,搜索词"我"并没有被单独划分出来,而是与"爱"一起作为一个词元"我爱"。在这种情况下,如果用户搜索"我",基于分词器2构建的索引将无法检索到包含"我爱中国"的文档,因为索引中没有单独的词元"我"。
非结构化日志分析思路
背景
我需要对服务器每天产生的大量日志文件进行分析,检索出持续时间过长的请求(一次请求会产生多条日志,并且分布在各处,由id标识)和sql查询,并且还要定位出所有的系统出错。
思路
- 建立索引,字段包括:时间,id,内容等
- 通过正则表达式提取每条日志的信息插入到索引中,同时用集合记录请求id
- 根据记录的请求id进行查询,直接查出该请求的全部日志,然后计算持续时间等数据
- 根据持续时间维护指定容量的
最小堆
(我们只需要查找耗时最长的n次请求,并且如果直接先计算全部请求的数据然后进行排序会消耗大量的内存) - sql同理
- 错误就更简单了,先分析每种出错类型的查询词,然后直接在指定字段检索即可。例如:
- "系统内部错误"
- "外部接口错误"
2024/8/6