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使用笔记的更多相关文章

  1. git-简单流程(学习笔记)

    这是阅读廖雪峰的官方网站的笔记,用于自己以后回看 1.进入项目文件夹 初始化一个Git仓库,使用git init命令. 添加文件到Git仓库,分两步: 第一步,使用命令git add <file ...

  2. js学习笔记:webpack基础入门(一)

    之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...

  3. SQL Server技术内幕笔记合集

    SQL Server技术内幕笔记合集 发这一篇文章主要是方便大家找到我的笔记入口,方便大家o(∩_∩)o Microsoft SQL Server 6.5 技术内幕 笔记http://www.cnbl ...

  4. PHP-自定义模板-学习笔记

    1.  开始 这几天,看了李炎恢老师的<PHP第二季度视频>中的“章节7:创建TPL自定义模板”,做一个学习笔记,通过绘制架构图.UML类图和思维导图,来对加深理解. 2.  整体架构图 ...

  5. PHP-会员登录与注册例子解析-学习笔记

    1.开始 最近开始学习李炎恢老师的<PHP第二季度视频>中的“章节5:使用OOP注册会员”,做一个学习笔记,通过绘制基本页面流程和UML类图,来对加深理解. 2.基本页面流程 3.通过UM ...

  6. NET Core-学习笔记(三)

    这里将要和大家分享的是学习总结第三篇:首先感慨一下这周跟随netcore官网学习是遇到的一些问题: a.官网的英文版教程使用的部分nuget包和我当时安装的最新包版本不一致,所以没法按照教材上给出的列 ...

  7. springMVC学习笔记--知识点总结1

    以下是学习springmvc框架时的笔记整理: 结果跳转方式 1.设置ModelAndView,根据view的名称,和视图渲染器跳转到指定的页面. 比如jsp的视图渲染器是如下配置的: <!-- ...

  8. 读书笔记汇总 - SQL必知必会(第4版)

    本系列记录并分享学习SQL的过程,主要内容为SQL的基础概念及练习过程. 书目信息 中文名:<SQL必知必会(第4版)> 英文名:<Sams Teach Yourself SQL i ...

  9. 2014年暑假c#学习笔记目录

    2014年暑假c#学习笔记 一.C#编程基础 1. c#编程基础之枚举 2. c#编程基础之函数可变参数 3. c#编程基础之字符串基础 4. c#编程基础之字符串函数 5.c#编程基础之ref.ou ...

随机推荐

  1. 最火的Android开源项目(完结篇)

    65. AndroidSideMenu AndroidSideMenu能够让你轻而易举地创建侧滑菜单.需要注意的是,该项目自身并不提供任何创建菜单的工具,因此,开发者可以自由创建内部菜单. 66. A ...

  2. [转]把项目从VS2005升级到VS2013

    原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://rangercyh.blog.51cto.com/1444712/1394348 ...

  3. Offer是否具有法律效力?

    版权声明:原创作品,同意转载,转载时请务必以超链接形式标明文章原始出版.作者信息和本声明.否则将追究法律责任.本文地址: http://blog.csdn.net/jobchanceleo/archi ...

  4. drop table big_table 调试

    (gdb) thread apply all bt Thread (Thread )): # # /storage/innobase/os/os0sync.cc: # ) at /usr/src/my ...

  5. javascript笔记08:javascript的if...else语句

    案例代码如下: <!DOCTYPE html> <html> <body> <p>点击这个按钮,获得基于时间的问候.</p> <but ...

  6. iOS/object-c: 枚举类型 enum,NS_ENUM,NS_OPTIONS

    一般情况下,我们采用C风格的enum关键字可以定义枚举类型. enum{ UIViewAnimationTransitionNone, UIViewAnimationTransitionFlipFro ...

  7. Memcached原理

    Memcached是一套高性能的.分布式内存对象缓存系统.它由C写成,以Key/Value的方式将数据储存在内存中. 一.Memcached特性 Memcached作为高速运行的分布式缓存服务器,具有 ...

  8. sklearn两种保存模型的方式

    作者:卢嘉颖 链接:https://www.zhihu.com/question/27187105/answer/97334347 来源:知乎 著作权归作者所有,转载请联系作者获得授权. 1. pic ...

  9. Python教程:ORM连接Sqlite数据库,软件架构基础

    python语言因其语法简单易学习,且高效率应用广,近几年来发展迅猛,一度进入编程语言排行榜前六名.为了使程序员能更快的学习Python语言,所以写的此教程.也可以说是对自己学习的总结.但文章尽量会使 ...

  10. ECMA5 Array 新增API reduce

    1)reduce:相当与迭代: [].reduce(function(previous,current,index,array){ return previous * current;//相当与做阶乘 ...