Whoosh使用手册(一)

时间:2023-02-03 23:23:23
最近想做一个搜索引擎,当然少不了看下闻名遐迩的Lucene,不得不说确实非常出色,但是对于python的实现pylucene确是差强人意,首先它不是纯python实现而是做了一层包装到头来还是使用java,依赖于JDK不说安装步骤繁琐至极,而且Lucene可用的中文分词词库非常之多但是由于这层粘合关系很多都用不上,最终还是放弃,不过平心而论如果用Java实现的确很完美。其它的有sphinx以及基于它实现的专门用于中文的coreseek,不过看了下好像是基于SQL语言的,对于我要做的事情好像关系不大;还有用C++写的xapian框架,可以说是一片好评啊,速度精度都非常不错,但最终还是看上了纯python实现的Whoosh,首先对于python使用来说非常简单,就是一个模块,easy_install就行,但是搜了一下国内的资料非常之少,没有办法,就把它的文档翻译一下吧~~今天开始
     
QuickStart 
    Whoosh是一个索引文本和搜索文本的类库,他可以为你提供搜索文本的服务,比如如果你在创建一个博客的软件,你可以用whoosh为它添加添加一个搜索功能以便用户来搜索博客的入口
下面是一个简短的例子:
>>>from whoosh.index import create_in
>>>from whoosh.fields import *
>>>schema = Schema(title = TEXT(stored = True),path =ID(stored=True),content=TEXT)
>>>ix =create_in("indexer",schema)(这里的“indexer”实际上是一个目录,因此按照这个步骤来会出错,你得先创建目录,译者注)
>>>writer = ix.writer()
>>>writer.add_document(title=u"Firstdocument",path=u"/a",
content = u"this is the first document we've add!")
>>> writer.add_document(title=u"Second document",path=u"/b",
... 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", "path": u"/a"}

Index和Schema对象

在开始使用whoosh之前,你需要一个index对象,在你第一次创建index对象时你必须定义一个Schema对象,Schema对象列出了Index的所有域。一个域就是Index对象里面每个document的一个信息,比如他的题目或者他的内容。一个域能够被索引(就是能被搜索到)或者被存储(就是得到索引之后的结果,这对于标题之类的索引非常有用)
下面这个schema对象有两个域,“title”和“content”

from whoosh.fields import Schema,TEXT
schema = Schema(title=TEXT,content=TEXT)

当你创建index的时候你创建一次schema对象就够了,schema是序列化并且和index存储的。
当你创建索引对象的时候,需要用到关键字参数来将域名和类型建立映射关系,域的名字和类型决定了你在索引什么和什么事可搜索的。whoosh有很多非常有用的预定义域类型,你可以非常容易的创建他们。如下:
whoosh.fields.ID
这种类型简单地索引(选择性存储)这个域里面所有的值作为一个单元(意思就是它不会把里面的词分开)这个对于像存储文件路径,URL,日期等等非常有用
whoosh.fileds.STROED
这个域存储文本但是不索引,他不被索引也不可被搜索,当你需要给用户展示文本搜索结果信息的时候非常有用
whoosh.fileds.KEYWORD
这种类型是为空格或者逗号分词的关键字设计的。他可以被索引和被搜索到(并且选择性的存储)。为了保存空格他不支持词组搜索
whoosh.fields.TEXT
这是正文文本,他索引(并且选择性存储)文本并且存储词语位置来支持短语搜索
whoosh。fields.NUMERIC
数字类型,可以存储整数和浮点数
whoosh.fields.BOOLEAN
布尔类型
whoosh.fields.DATETIME
日期类型,以后有详细介绍
whoosh.fields.NGRAM和whoosh.fields.NGRAMWORDS
这种类型把文本分成n-grams(以后详细介绍)
(为了简便,你可以不给域类型传递任何参数,你可以仅仅给出类型名字whoosh会为你创造类的实例)

from whoosh.fields import Schema,STORED,ID,KEYWORD,TEXT

schema = Schema(title=TEXT(stored=True),content=TEXT,
path=ID(stored=True),tags=KEYWORD,icon=STORED)

一旦你有了schema对象,你可以用create_in函数创建索引:

import os.path
from whoosh.fields import create_in

if not os.path.exists("index"):
os.mkdir("index")
ix =create_in("index",schema)

(这创造了一个存储对象来包含索引,存储对象代表存储索引的媒介,通常是文件存储,也就是存在目录的一系列文件)
在你创建索引之后,你可以通过open_dir函数方便地打开它

from whoosh.index import open_dir

ix = open_dir("index")


IndexWriter对象

好了我们有了索引对象现在我们可以添加文本。索引对象的writer()方法返回一个能够让你给索引添加文本的IndexWriter对象,IndexWriter对象的add_document(**kwargs)方法接受关键字参数:

writer = ix.writer()
writer.add_document(title=u"My document", content=u"This is mydocument!",
path=u"/a",tags=u"first short", icon=u"/icons/star.png")
writer.add_document(title=u"Second try", content=u"This is thesecondexample.",path=u"/b", tags=u"second short", icon=u"/icons/sheep.png")
writer.add_document(title=u"Third time's the charm",content=u"Examples aremany."path=u"/c", tags=u"short", icon=u"/icons/book.png")
writer.commit()


两个重点:
1.你不必要把每一个域都填满,whoosh不关系你是否漏掉某个域
2.被索引的文本域必须是unicode值,被存储但是不被索引的域(STORED域类型)可以是任何和序列化的对象
如果你需要一个既要被索引又要被存储的文本域,你可以索引一个unicode值但是存储一个不同的对象(某些时候非常有用)

writer.add_document(title=u"Title to be indexed",_stored_title=u"Stored title")


使用commit()方法让IndexWriter对象将添加的文本保存到索引
writer.commit()

Searcher对象

在搜索文本之前,我们需要一个Searcher对象
searcher = ix.searcher()

推荐用with表达式来打开搜索对象以便searcher对象能够自动关闭(searcher对象代表打开的一系列文件,如果你不显式的关闭他们,系统会慢慢回收他们以至于有时候会用尽文件句柄)

with in.searcher() as searcher:
...

这等价于:

try:
searcher =ix.searcher()
...
finally:
searcher.close()

Searcher对象的search方法使用一个Query对象,你可以直接构造query对象或者用一个queryparser来得到一个查询语句
#Construct query objects directly

from whoosh.query import *
myquery =And([Term("content",u"apple"),Term("content","bear")])



用parser得到一个查询语句,你可以使用默认的qparser模块里面的queryparser。QueryParser构造器的第一个参数是默认的搜索域,这通常是“正文文本”域第二个可选参数是用来理解如何parse这个域的schema对象:
#Parse a query string

from whoosh.qparser import QueryParser
parser = QueryParser("content",ix.schema)
myquery = parser.parse(querystring)


一旦你有了Searcher和query对象,你就可以使用Searcher对象的search()方法进行查询并且得到一个结果对象

>>>results = searcher.search(myquery)
>>>print len(results)
1
>>>print results[0]
{"title": "Second try", "path": /b,"icon":"/icon/sheep.png"}

默认的QueryParser实现了一种类似于lucene的查询语言,他允许你使用连接词AND和OR以及排除词NOT和组合词together来搜索,他默认使用AND将从句连结起来(因此默认你所有的查询词必须都在问当中出现)

>>> print(parser.parse(u"render shade animate"))
And([Term("content", "render"), Term("content", "shade"),Term("content", "animate")])

>>> print(parser.parse(u"render OR (title:shadekeyword:animate)"))
Or([Term("content", "render"), And([Term("title", "shade"),Term("keyword", "animate")])])

>>> print(parser.parse(u"rend*"))
Prefix("content", "rend")


Whoosh处理结果包含额外的特征,例如:
1.按照结果索引域的值排序,而不是按照相关度
2.高亮显示原文档中的搜索词
3.扩大查询词给予文档中找到的少数值
4.分页显示(例如显示1-20条结果,第一到第四页的结果)

关于如何搜索后面有详细介绍

好,第一篇到此为止,后面会陆陆续续地翻译出来,算是开个头吧