zoukankan      html  css  js  c++  java
  • 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字段查找文档,然后删除之。

      

     1 from whoosh.fields import Schema, ID, TEXT
     2 
     3 schema = Schema(path = ID(unique=True), content=TEXT)
     4 ix = index.create_in("index")
     5 writer = ix.writer()
     6 writer.add_document(path=u"/a", content=u"The first document")
     7 writer.add_document(path=u"/b", content=u"The second document")
     8 writer.commit()
     9 
    10 writer = ix.writer()
    11 # Because "path" is marked as unique, calling update_document with path="/a"
    12 # will delete any existing documents where the "path" field contains "/a".
    13 writer.update_document(path=u"/a", content="Replacement for the first document")
    14 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属性即可

      

  • 相关阅读:
    Lua中的loadfile、dofile、require详解
    100GB以上超大文件上传和断点续传服务器的实现
    50GB以上超大文件上传和断点续传服务器的实现
    20GB以上超大文件上传和断点续传服务器的实现
    10GB以上超大文件上传和断点续传服务器的实现
    Flash 以上超大文件上传和断点续传服务器的实现
    WebUploader 以上超大文件上传和断点续传服务器的实现
    HTML5 以上超大文件上传和断点续传服务器的实现
    VUE 以上超大文件上传和断点续传服务器的实现
    B/S 以上超大文件上传和断点续传服务器的实现
  • 原文地址:https://www.cnblogs.com/shonelau/p/5805739.html
Copyright © 2011-2022 走看看