whoosh使用笔记

Whoosh是一个纯python实现的全文搜索组件,简单易用

安装

pip install whoosh

whoosh 使用流程

  1. 创建索引对象(创建对象前,要先定义索引schema)
  2. 添加文档到索引中
  3. 通过关键词搜索

官方示例

from whoosh.index import create_in
from whoosh.fields import *

#定义索引schema,确定索引字段
schema = Schema(title=TEXT(stored=True), content=TEXT)

#创建索引对象
if not os.path.exists("index"):
  os.mkdir("index")
ix = create_in("index", schema)

#添加文档到索引中
writer = ix.writer()
writer.add_document(title=u"First document", content=u"This is the first document we've added!")
writer.add_document(title=u"Second document",content=u"The second one is even more interesting!")
writer.commit()

#通过关键词搜索
from whoosh.qparser import QueryParser
with ix.searcher() as searcher:
  query = QueryParser("content", ix.schema).parse("first")
  results = searcher.search(query)
  results[0]
...
{"title": u"First document"}

使用中需要思考的那些问题

第一次使用,按照官方示例小试了一把,顺利获取搜索结果,至此简单入门
实际使用中发现,还是有许多问题需要继续学习解决的,总结如下

问题一

实际应用中,我们不可能将所有文档一口气儿添加到索引中,如果我们每次添加文档都新建索引对象的话
肯定会把以前的内容覆盖,那我们怎么获取向已有索引中添加文档呢?

解决方法:

if index.exists_in('index'):
  ix = index.open_dir('index')
else:
  ix = index.create_in('index', schema)

问题二

以上搜索示例只是匹配单个关键词,但是我们之所以用搜索引擎,都是想要同时匹配多个关键词
解决方法:

  1. “或” 使用连接词 “OR”
    query = QueryParser("content", ix.schema).parse("first OR second")
    
  2. “并且” 使用连接词 “AND”
    query = QueryParser("content", ix.schema).parse("first AND second")
    

问题三

whoosh 只支持英文检索,那我们想检索中文怎么办?
whoosh默认是基于正则表达式进行分词的,想要支持中文,只需

from whoosh.analysis import RegexAnalyzer

analyzer = RegexAnalyzer(ur"([\u4e00-\u9fa5])|(\w+(\.?\w +)*)")
schema = Schema(title=TEXT(stored=True),content=TEXT(stored=True,analyzer=analyzer))

问题四

实际应用过程中,我们不可能只是一味的向索引中添加文档,肯定会涉及到对索引中已有文档进行修改或删除

1、修改文档

对于修改文档,在定义的索引schema中,至少要包含一个“unique”字段,whoosh会根据“unique”字段内容
搜索相应文档去删除,然后重新添加

schema = Schema(id = ID(unique=True), content=TEXT)

ix = index.create_in("index")

writer = ix.writer()
writer.update_document(id=u"1", content="Replacement for the first document")
writer.commit()

2、删除文档(此处有个坑)

官方示例

ix.delete_by_term('path', u'/a/b/c')
ix.commit()

结果报错

AttributeError: 'FileIndex' object has no attribute 'commit'

看了源码才知道,索引对象的delete_by_term方法内部已经完成了commit操作,
所有只需

ix.delete_by_term('id', u'1')

即可,其相当于

writer = ix.writer()
writer.delete_by_term('id', u"1")
writer.commit()

继续学习的话,还是看官方文档:http://whoosh.readthedocs.io/en/latest/quickstart.html