自己动手写分布式搜索引擎
上QQ阅读APP看书,第一时间看更新

3.3.10 使用Filter筛选搜索结果

可以定义Filter类过滤查询结果,也可以缓存和重用Filter。如下条件可用Filter来实现:

● 根据不同的安全权限显示搜索结果。

● 仅查看上个月的数据。

● 在某个类别中查找,例如在分类统计查询中,根据分类列的有效取值缩小查询范围。

Filter返回一个DocIdSet,其中包含符合条件的文档编号。DocIdSet是一个存储文档编号的集合。例如:

        IndexReader reader= …
        OpenBitSet bitSet = new OpenBitSet(reader.maxDoc()); // 假设所有的文档都不在集合内
        bitSet.set( 0 ); //让第一个文档在集合内

Filter过滤整个索引,得到DocIdSet。

        public abstract class Filter implements java.io.Serializable {
          public abstract DocIdSet getDocIdSet(IndexReader reader) throws
        IOException;
        }

下面定义一个BestDriversFilter,把搜索结果限定到score是5的司机。

        public class BestDriversFilter extends Filter{
            @Override
            public DocIdSet getDocIdSet(IndexReader reader) throws IOException {
              OpenBitSet bitSet = new OpenBitSet( reader.maxDoc() );
              //查询出score是5的文档
              TermDocs termDocs = reader.termDocs( new Term( "score", "5" ) );
              while ( termDocs.next() ) {
                  bitSet.set( termDocs.doc() ); // 把符合条件的文档对应的位置设为1
              }
              return bitSet;
            }
        }

在查询中使用这个Filter:

        Hits h = searcher.search(tq, filter);

完整的代码:

        Filter bestDriversFilter = new BestDriversFilter();
        //query不变,增加bestDriversFilter
        ScoreDoc[] hits = isearcher.search(query, bestDriversFilter, 10).scoreDocs;
        //因为不是每个司机都能得5分,所以返回的结果可能比以前少了