lucene的排序过滤和分页

三、排序过滤和分页
      仅仅把东西搜出来是不够的,好的检索工具还应当能够对检索的结果进行排序,优先将最相关的内容送出
  或是按照某种规则,将检索结果送出。
  1.文档得分规则
      文档得分主要是由4部分内容来决定,即tf(词条频率)、idf(反转文档频率)、boost(Field的激励因子)
  和lengthNorm(长度因子)
      tf:某个关键字在某文档中出现次数的平方根
      idf:Math.log(numDocs/docFreq+1)+1.0   (numDocs:表示索引中总共的文档数量,docFreq:当前检索
          的关键字的文档总数)
      lengthNorm:在lucene的底层实现中,lengthNorm是一种固定值,它无需在索引时指定,只需要跟随创建
          索引过程,被写入索引中。
      boost:文档的boost值一般情况下默认为1.0,在建立索引时可通过预先人为的指定Document或Field的
          boost值,来改变搜索时文档的得分,从而改变文档在搜索结果中的排序位置。
  2.使用Sort排序
       该类有6种构造函数
       public Sort()
       public Sort(String field) 默认为降序
       public Sort(String field,boolean reverse)
       public Sort(String[] fields)
       public Sort(SortField field)
       public Sort(SortField[] fields)
       Sort可以对单一的Field进行排序,但是对多个Field的排序就必须要借助SortField类了。SortField类
    是个包装类,它能描述Field和reverse(排序)信息,在搜索结果中有很多记录时,应该正确的指定Field
    的类型,这样对排序过程的效率会有很大的提高。
       排序有多种
       a.按文档得分进行排序:这是lucene默认的排序方式
             如:Hits hist=searcher.search(q,Sort.RELEVANCE);   Sort.RELEVANCE表示当前的排序法则
         是按照文档的得分进行降序排列
       b.按文档的内部ID号来排序:在建立索引的时候,lucene会为每个文档建立一个内部的ID号
             如:Hits hits=searcher.search(q,Sort.INDEXORDER)   Sort.INDEXORDER表示排序法则是按
         照文档的内部ID号来排序
       c.按一个或多个Field来排序:把每个Field封装成SortField,然后以SortField[]数组的形式传入Sort类
       注意:比较字符串时,Locale信息的不同,很有可能会影响到比较的结果,因此SortField类有这样的构
       造函数,可以帮助指定Locale信息
          public SortField(String field,Locale locale)
          public SortField(String field,Locale locale,boolean reverse)
       当指定Locale后,lucene才可以正确的对字符串进行比较,从而正确的排序。不过大多数情况下,使用Sort
       进行排序时,排序的内容多为int型或是日期型。即便需要进行字符串的比较,也最好使用仅包含ASCII的
       字符串Field进行,这样可以确保排序的正确,同时,尽量提高排序的效率。
  3.搜索时使用过滤器
    简单示例:

Java代码 复制代码

  1. public class MySecurityFilter extends Filter{   
  2. public static final int SECURITY=0;   
  3. public BitSet bits(IndexReader reader) throws IOException{   
  4. //先初始化一个BitSet对象 
  5. final BitSet bits=new BitSet(reader.maxDoc());   
  6. //将整个集合置为true,表示当前集合内的所有文档都是可以被检索到的
  7.        bits.set(0,bits.size()-1);   
  8. //构造一个Term对象,代表最高安全级别
  9.        Term term=new Term("securitylevel",SECURITY+"");   
  10. //从索引中取出具有最高安全级别的文档
  11.        TermDocs termDocs=reader.termDocs(term);   
  12. //遍历每个文档
  13. while(termDocs.next()){   
  14.           bits.set(termDocs.doc(),false);   
  15.        }   
  16.       retrun bits;   
  17.     }   
  18. }  
        public class MySecurityFilter extends Filter{
            public static final int SECURITY=0;
            public BitSet bits(IndexReader reader) throws IOException{
               //先初始化一个BitSet对象 
               final BitSet bits=new BitSet(reader.maxDoc());
               //将整个集合置为true,表示当前集合内的所有文档都是可以被检索到的
               bits.set(0,bits.size()-1);
               //构造一个Term对象,代表最高安全级别
               Term term=new Term("securitylevel",SECURITY+"");
               //从索引中取出具有最高安全级别的文档
               TermDocs termDocs=reader.termDocs(term);
               //遍历每个文档
               while(termDocs.next()){
                  bits.set(termDocs.doc(),false);
               }
              retrun bits;
            }
        }
      

        或者:

Java代码 复制代码

  1. public class MySecurityFilter extends Filter{   
  2. public static final int SECURITY=0;   
  3. public BitSet bits(IndexReader reader) throws IOException{   
  4. //先初始化一个BitSet对象 
  5. final BitSet bits=new BitSet(reader.maxDoc());   
  6. //将整个集合置为true,表示当前集合内的所有文档都是可以被检索到的
  7.        bits.set(0,bits.size()-1);   
  8. //构造一个Term对象,代表最高安全级别
  9.        Term term=new Term("securitylevel",SECURITY+"");   
  10. //初始化一个IndexSearcher对象
  11. //查找securitylevel这个Field的值为SECURITY的文档
  12.        IndexSearcher searcher=new IndexSearcher(term);   
  13.        Hits hits=searcher.search(new TermQuery(term));   
  14. for(int i=0;i<hits.length();i++){   
  15.           bits.set(hits.id(i),false);   
  16.        }   
  17.       retrun bits;   
  18.     }   
  19. }  
        public class MySecurityFilter extends Filter{
            public static final int SECURITY=0;
            public BitSet bits(IndexReader reader) throws IOException{
               //先初始化一个BitSet对象 
               final BitSet bits=new BitSet(reader.maxDoc());
               //将整个集合置为true,表示当前集合内的所有文档都是可以被检索到的
               bits.set(0,bits.size()-1);
               //构造一个Term对象,代表最高安全级别
               Term term=new Term("securitylevel",SECURITY+"");
               //初始化一个IndexSearcher对象
               //查找securitylevel这个Field的值为SECURITY的文档
               IndexSearcher searcher=new IndexSearcher(term);
               Hits hits=searcher.search(new TermQuery(term));
               for(int i=0;i<hits.length();i++){
                  bits.set(hits.id(i),false);
               }
              retrun bits;
            }
        }
       

        注意:Filter实际上在进行真正的查询之前,已经遍历过一次一遍索引了,因此无
        论使用何种Filter,都不应该忽视它对查询效率的影响。
   4.在结果中查询(QueryFilter)
          在QueryFilter的bits方法中,调用IndexSearcher方法,对注入的Query进行一次
     检索,然后在要被返回的BitSet中,将检索结果所对应的文档标记为true,即过滤掉了
     所有不再检索结果范围内的文档。

转载于:https://www.cnblogs.com/jerry-weijb/archive/2010/09/01/1814803.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值