whoosh使用笔记
1. whoosh安装
pip install Whoosh
2. 添加索引
第一步:生成schema
第二步:根据schema生成index.index就是一个目录中的一堆文件
(针对某个目录,调用一个已存在的索引名字的index.create_in方法,会清空已存在索引的内容!).若想清除索引,可以把目录中的索引文件删掉。若目录中仅有一个索引,可以删除整个目录,然后从新生成目录即可。
第三步:根据index生成writer(调用index.writer())
第四步:writer.add_document即可
由于打开writer时会lock住索引文件,因此在某一时间,仅有一个线程或进程可打开一个writer.打开一个已被lock的writer会抛出LockError.whoosh提供了AsyncWriter和BufferWriter可以在lock状况下工作。
对于某字段,可以索引与存储分开,使用stored_<fieldname>字段即可。 writer不commit, 或者cancel, 其他线程或进程不可再打开writer
3. 编辑和删除索引
删除操作使用writer的以下三个方法
delete_document(docnum)方法 (docnum是索引查询结果的每条结果记录的docnum属性)
delete_by_term(field_name,termtext)方法 (特别适合删除ID,或KEYWORD字段)
delete_by_query(query)
删除一个index仅仅是把该document的docnum添加到一个deleted index列表中
编辑即replace,可以使用上面的delete_*方法删除后,使用add_document添加。也可以使用update_document。使用该方法时,在schema里定义的字段,至少有一个字段是定义有unique属性的。whoosh使用该unique字段查找文档,然后删除之。
from whoosh.fields import Schema, ID, TEXT schema = Schema(path = ID(unique=True), content=TEXT)
ix = index.create_in("index")
writer = ix.writer()
writer.add_document(path=u"/a", content=u"The first document")
writer.add_document(path=u"/b", content=u"The second document")
writer.commit() writer = ix.writer()
# Because "path" is marked as unique, calling update_document with path="/a"
# will delete any existing documents where the "path" field contains "/a".
writer.update_document(path=u"/a", content="Replacement for the first document")
writer.commit()
其实unique字段和update_document就是delete和add的一种shortcut.
4. 查询索引
第一步:若索引已添加了,调用open_dir("dir of index")即可返回index,若出现exception则说明,还没有添加任何索引。
第二步:通过调用index.searcher(),根据index生成searcher. searcher就是打开的一堆文件,用完一定要关闭。 searcher有很多获取索引信息的有用方法,
比如lexicon(fieldname):得到某字段的全部分词。当然其中最重要的方法就是search方法。
第三步: 生成查询对象, 有两种方式:
直接构建query对象:
类似于:myquery = And([Term("content", u"apple"), Term("content", "bear")])
query language:
就是解析查询的字符串后,生成一个query对象
step1, 通过 parser=QueryParser("content",index.schema),先生成一个parser. 其中content是若不定义字段时,默认的查询字段。
step2, 调用parser.parse(querystring),分析query,生成query对象
第四步: 以query对象为参数调用searcher的search方法.得到查询result.
默认的search方法的results最多仅返回10个匹配的文档。若想返回更多,就要使用limit参数查询了:
results = searcher.search(query,limit=20). 若要得到全部的结果,可把limit=None.
search_page(query,page)方法可已让你得到某page的结果,默认是一页10个hit,可以使用pagelen参数调整
search_page(query,page,pagelen=20)
Results对象表现的就像是list一样:可进行len(results), results[0], results[0:2]
由于默认的results仅返回10条记录,所以results的scored_length()可能会小于索引中实际匹配的总条目数。
而调用len(result),其实是运行了一个快速的非计分版本的查询,得到的是匹配的全部文档数。这个调用通常很快速,但是若是遇到一个很大的索引的话,会有明显的延迟。
若要避免这种延迟,可以使用has_exact_length(), estimated_length(), and estimated_min_length() 去估算匹配的文档数目而不是使用len()
len()返回的是全部的满足条件的文档数量,estimate_*返回的是预估的数量,若预估已确切,则是确切的数量.scored_length()返回的数值小于等于limit
可以在search方法中设置terms=True,来记录:在terms查询中,哪个term匹配哪个document.然后通过results.matched_terms()调用,返回results中匹配了哪些term.
在hit中调用matched_terms()返回,在hit中匹配了哪些terms, 设置terms=True,还可以加速查询结果高亮的处理
5. 使用查询结果
scoring:
一般而言,result文档列表使用score值来排序。whoosh.scoring模块包含了多个不同scoring算法的实现,默认是BM25F.
当初始化searcher时可以用weighting关键字去替换默认的scoring算法。可以继承WeightingModel实现定制权重算法.
过滤结果:
对searcher对象的search方法使用filter参数,可以限定results中的允许的文档。也可以使用mask参数对限定results中不允许的文档.参数值可以是query对象,results对象,也可以是承载docnum的set集合。
排序和分类:
对查询结果的排序和分类是基于facet的。在查询结果中的每个文档里的每个facet都会和一个值相关,使用这个数值,可以让你对结果排序或分组。
查询结果在默认情况下,是scoring最高的值排在前面。可以使用在search方法中使用sortedby参数定义其他的条件对查询结果排序。
生成一个可排序的字段:
为了可以针对某字段排序,在定义schema时,需对该字段添加sortable=True参数.也可以针对没定义sortable=True的字段排序,但是比较没有效率。
合并results对象:
Results.extend(results):把results加在Results后
Results.filter(results):把results中的文档从Results中移除
Results.upgrade(results):把出现在results中的Results文档,移到Results的前头
Results.upgrade_and_extend(result),出现在results中的Results文档,移动到Results的前头,而那些不在Results中的results文档,则添加到Results后头。
6. 摘要并高亮查询结果
高亮的过程就是一个pipeline的处理过程,和4个元件相关:
Fragments : 基于匹配的term在文档中的位置,把原始的文档砍成__fragments__
Scorers: 给每个fragment赋一个分值,允许系统根据分值排出最好的fragment.
Order functions: 控制展示给用户的fragment,是展示先出现在文档里的fragment,还是展示score最高的fragment.
Formatters: 把对应的fragment格式化为用户可读格式,如html
在对文本进行高亮处理前,需要去除格式标签,比如:html,和 wiki tags.
results = mysearcher.search(myquery)
for hit in results:
print(hit["title"])
# Assume "content" field is stored
print(hit.highlights("content"))
若高亮的字段没有stored在index中,则需要通过其他途径得到这个字段的text.
whoosh默认仅从文本的前32k字符中抽取fragment. 可以通过调整参数来增加这个值。
results = mysearcher.search(myquery)
results.fragmenter.charlimit = 100000
或者
results.fragmenter.charlimit = None 直接关闭限制
也可以初始化一个定制的framenter, 直接在fragment上设置字符限制:
sf = highlight.SentenceFragmenter(charlimit=100000)
results.fragmenter = s
定制高亮:
fragment的数量:
可以使用top参数控制每个文档返回的fragment的数量
print hit.highlights("content", top=5)
fragment的size:
fragmenter的maxchar属性控制fragment的最大长度,默认是200. surround属性控制fragment里关键字前后截取的背景文字长度,默认是20
# Allow larger fragments
results.fragmenter.maxchars = 300
# Show more context before and after
results.fragmenter.surround = 50
Fragmenter:
Fragmenter控制如何从原始文本中提取摘录文字. Whoosh.hightlight包里已有以下预制的fragmenter:
whoosh.highlight.ContextFragmenter (默认)
这是一个默认的智能fragment,可以发现匹配的term, 并抽取周围的文字生成 fragment. 这个fragmenter只产生包含匹配term的fragment.
whoosh.highlight.SentenceFragmenter
依标点符号,按句子抽取
whoosh.highlight.WholeFragmenter
返回整个文本作为fragment,高效(不做处理,当然高效)适合小文本
不同的fragmenter有不同的选项参数
Scorer:
Scorer是一个可调用的对象,使用fragment作为参数,返回一个可排序的值(值越大,代表该fragment质量越好)。 高亮系统使用这个值去挑选出展示给用户的最佳fragment.
#定义一个新的scorer
def StandardDeviationScorer(fragment):
"""Gives higher scores to fragments where the matched terms are close
together.
"""
# Since lower values are better in this case, we need to negate the
# value
return 0 - stddev([t.pos for t in fragment.matched])
#使用这个scorer
results.scorer = StandardDeviationScorer
Order:
order是一个函数,该函数以fragment为参数,返回一个可排序的值,通过该值对fragment进行排序。
whoosh.highlight模块有一下的排序函数:
FIRST(默认的)
按出现顺序
SCORE:
按得分顺序
还有其他不常用的: LONGER长fragment优先,SHORTER短fragment优先
使用非默认的排序函数:
results.order = hightlight.SCORE
Formatter:
formatter负责控制分值最高的fragment如何以格式化的方式呈现给用户。通过设置不同的formatter可以返回任何格式,包括:html,genshi事件流,SAX事件生成器,等。
highlight模块有一下预置实现
whoosh.highlight.HtmlFormatter
以带class属性的html标签包围的方式返回匹配的term
whoosh.highlight.UppercaseFormatter
把匹配的term以大写字母呈现
whoosh.highlight.GenshiFormatter
输出一个genshi事件流
替换formatter的方式和上面替换其他三个元件的方式一致,更改results.formatter属性即可
whoosh使用笔记的更多相关文章
- git-简单流程(学习笔记)
这是阅读廖雪峰的官方网站的笔记,用于自己以后回看 1.进入项目文件夹 初始化一个Git仓库,使用git init命令. 添加文件到Git仓库,分两步: 第一步,使用命令git add <file ...
- js学习笔记:webpack基础入门(一)
之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...
- SQL Server技术内幕笔记合集
SQL Server技术内幕笔记合集 发这一篇文章主要是方便大家找到我的笔记入口,方便大家o(∩_∩)o Microsoft SQL Server 6.5 技术内幕 笔记http://www.cnbl ...
- PHP-自定义模板-学习笔记
1. 开始 这几天,看了李炎恢老师的<PHP第二季度视频>中的“章节7:创建TPL自定义模板”,做一个学习笔记,通过绘制架构图.UML类图和思维导图,来对加深理解. 2. 整体架构图 ...
- PHP-会员登录与注册例子解析-学习笔记
1.开始 最近开始学习李炎恢老师的<PHP第二季度视频>中的“章节5:使用OOP注册会员”,做一个学习笔记,通过绘制基本页面流程和UML类图,来对加深理解. 2.基本页面流程 3.通过UM ...
- NET Core-学习笔记(三)
这里将要和大家分享的是学习总结第三篇:首先感慨一下这周跟随netcore官网学习是遇到的一些问题: a.官网的英文版教程使用的部分nuget包和我当时安装的最新包版本不一致,所以没法按照教材上给出的列 ...
- springMVC学习笔记--知识点总结1
以下是学习springmvc框架时的笔记整理: 结果跳转方式 1.设置ModelAndView,根据view的名称,和视图渲染器跳转到指定的页面. 比如jsp的视图渲染器是如下配置的: <!-- ...
- 读书笔记汇总 - SQL必知必会(第4版)
本系列记录并分享学习SQL的过程,主要内容为SQL的基础概念及练习过程. 书目信息 中文名:<SQL必知必会(第4版)> 英文名:<Sams Teach Yourself SQL i ...
- 2014年暑假c#学习笔记目录
2014年暑假c#学习笔记 一.C#编程基础 1. c#编程基础之枚举 2. c#编程基础之函数可变参数 3. c#编程基础之字符串基础 4. c#编程基础之字符串函数 5.c#编程基础之ref.ou ...
随机推荐
- 最火的Android开源项目(完结篇)
65. AndroidSideMenu AndroidSideMenu能够让你轻而易举地创建侧滑菜单.需要注意的是,该项目自身并不提供任何创建菜单的工具,因此,开发者可以自由创建内部菜单. 66. A ...
- [转]把项目从VS2005升级到VS2013
原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://rangercyh.blog.51cto.com/1444712/1394348 ...
- Offer是否具有法律效力?
版权声明:原创作品,同意转载,转载时请务必以超链接形式标明文章原始出版.作者信息和本声明.否则将追究法律责任.本文地址: http://blog.csdn.net/jobchanceleo/archi ...
- drop table big_table 调试
(gdb) thread apply all bt Thread (Thread )): # # /storage/innobase/os/os0sync.cc: # ) at /usr/src/my ...
- javascript笔记08:javascript的if...else语句
案例代码如下: <!DOCTYPE html> <html> <body> <p>点击这个按钮,获得基于时间的问候.</p> <but ...
- iOS/object-c: 枚举类型 enum,NS_ENUM,NS_OPTIONS
一般情况下,我们采用C风格的enum关键字可以定义枚举类型. enum{ UIViewAnimationTransitionNone, UIViewAnimationTransitionFlipFro ...
- Memcached原理
Memcached是一套高性能的.分布式内存对象缓存系统.它由C写成,以Key/Value的方式将数据储存在内存中. 一.Memcached特性 Memcached作为高速运行的分布式缓存服务器,具有 ...
- sklearn两种保存模型的方式
作者:卢嘉颖 链接:https://www.zhihu.com/question/27187105/answer/97334347 来源:知乎 著作权归作者所有,转载请联系作者获得授权. 1. pic ...
- Python教程:ORM连接Sqlite数据库,软件架构基础
python语言因其语法简单易学习,且高效率应用广,近几年来发展迅猛,一度进入编程语言排行榜前六名.为了使程序员能更快的学习Python语言,所以写的此教程.也可以说是对自己学习的总结.但文章尽量会使 ...
- ECMA5 Array 新增API reduce
1)reduce:相当与迭代: [].reduce(function(previous,current,index,array){ return previous * current;//相当与做阶乘 ...