您的位置:首页 > 其它

Lucene.NET的多关键排序和条件搜索(高级搜索篇)

2008-07-29 10:30 609 查看
1.Lucene排序

Lucene有内置的排序用IndexSearcher.search(query,sort)但是功能并不理想。我们需要自己实现自定义的排序。

这样的话得实现两个接口: ScoreDocComparator, SortComparatorSource
用IndexSearcher.search(query,new Sort(new SortField(String Field,SortComparatorSource)));
就看个例子吧:

这是一个建立索引的例子:

public void IndexSort() throws IOException { 
      IndexWriter writer = new IndexWriter("C://indexStore",new StandardAnalyzer(),true); 
      Document doc = new Document(); 
      doc.add(new Field("sort","1",Field.Store.YES,Field.Index.TOKENIZED)); 
      writer.addDocument(doc); 
      doc = new Document(); 
      doc.add(new Field("sort","4",Field.Store.YES,Field.Index.TOKENIZED)); 
      writer.addDocument(doc); 
      doc = new Document(); 
      doc.add(new Field("sort","3",Field.Store.YES,Field.Index.TOKENIZED)); 
      writer.addDocument(doc); 
      doc = new Document(); 
      doc.add(new Field("sort","5",Field.Store.YES,Field.Index.TOKENIZED)); 
      writer.addDocument(doc); 
      doc = new Document(); 
      doc.add(new Field("sort","9",Field.Store.YES,Field.Index.TOKENIZED)); 
      writer.addDocument(doc); 
      doc = new Document(); 
      doc.add(new Field("sort","6",Field.Store.YES,Field.Index.TOKENIZED)); 
      writer.addDocument(doc); 
      doc = new Document(); 
      doc.add(new Field("sort","7",Field.Store.YES,Field.Index.TOKENIZED));  
      writer.addDocument(doc); 
        writer.close(); 
} 
下面是搜索的例子: 
public void SearchSort1() throws IOException, ParseException { 
        IndexSearcher indexSearcher = new IndexSearcher("C://indexStore");
        QueryParser queryParser = new QueryParser("sort",new StandardAnalyzer()); 
        Query query = queryParser.parse("4");
        Hits hits = indexSearcher.search(query); 
        System.out.println("有"+hits.length()+"个结果"); 
        Document doc = hits.doc(0); 
        System.out.println(doc.get("sort")); 
} 
public void SearchSort2() throws IOException, ParseException { 
        IndexSearcher indexSearcher = new IndexSearcher("C://indexStore"); 
        Query query = new RangeQuery(new Term("sort","1"),new Term("sort","9"),true);
        //这个地方前面没有提到,它是用于范围的Query可以看一下帮助文档. 
        Hits hits = indexSearcher.search(query,new Sort(new SortField("sort",new MySortComparatorSource()))); 
        System.out.println("有"+hits.length()+"个结果"); 
        for(int i=0;i< hits.length();i++){ 
            Document doc = hits.doc(i); 
            System.out.println(doc.get("sort")); 
        } 
} 
public class MyScoreDocComparator implements ScoreDocComparator { 
   private Integer[]sort; 
   public MyScoreDocComparator(String s,IndexReader reader, String fieldname)
      throws IOException{ 
       sort = new Integer[reader.maxDoc()]; 
       for(int i = 0;i< reader.maxDoc();i++){ 
            Document doc =reader.document(i); 
            sort[i]=new Integer(doc.get("sort"));
        } 
    } 
    public int compare(ScoreDoc i, ScoreDoc j){ 
       if(sort[i.doc]>sort[j.doc]) 
            return 1; 
       if(sort[i.doc]< sort[j.doc]) 
           return -1; 
       return 0; 
    } 
    public int sortType(){ 
       return SortField.INT; 
    } 
    public Comparable sortValue(ScoreDoc i){ 
     // TODO 自动生成方法存根 
     return new Integer(sort[i.doc]); 
    } 
} 
public class MySortComparatorSource implements SortComparatorSource { 
   private static final long serialVersionUID = -9189690812107968361L; 
   public ScoreDocComparator newComparator(IndexReader reader, String fieldname) 
      throws IOException{ 
        if(fieldname.equals("sort")) 
            return new MyScoreDocComparator("sort",reader,fieldname); 
            return null; 
         } 
} 
SearchSort1()输出的结果没有排序,SearchSort2()就排序了。

2.多域搜索 MultiFieldQueryParser

1.如果想输入关键字而不想关心是在哪个Field里的就可以用MultiFieldQueryParser了。
用它的构造函数即可后面的和一个Field一样。
MultiFieldQueryParser.
 parse
(
String
[] queries,
String
[] fields,
BooleanClause.Occur
[] flags,
Analyzer
analyzer)

第三个参数比较特殊这里也是与以前lucene1.4.3不一样的地方,看一个例子就知道了。
String[] fields = {"filename", "contents", "description"};
BooleanClause.Occur[] flags = {BooleanClause.Occur.SHOULD,
BooleanClause.Occur.MUST,//在这个Field里必须出现的
BooleanClause.Occur.MUST_NOT};//在这个Field里不能出现
MultiFieldQueryParser.parse("query", fields, flags, analyzer);

2.多索引搜索 MultiSearcher
在构造的时候传进去一个Searcher数组即可

3.过滤器Filter

看个例子:
public void FilterTest() throws IOException, ParseException { 
        IndexWriter indexWriter = new IndexWriter("C://FilterTest",new StandardAnalyzer(),true); 
        Document doc = new Document(); 
        doc.add(new Field("name","程序员之家",Field.Store.YES,Field.Index.TOKENIZED)); 
        indexWriter.addDocument(doc); 
        doc=new Document(); 
        doc.add(new Field("name","程序员杂志",Field.Store.YES,Field.Index.TOKENIZED)); 
        indexWriter.addDocument(doc); 
        indexWriter.close(); 
        Query query = null; 
        Hits hits = null; 
        IndexSearcher indexSearcher = new IndexSearcher("C://FilterTest"); 
        QueryParser queryParser = new QueryParser("name",new StandardAnalyzer()); 
        query = queryParser.parse("程序"); 
        hits = indexSearcher.search(query,new Filter(){ 
            @Override 
            public BitSet bits(IndexReader reader) throws IOException{ 
               BitSet bit = new BitSet(reader.maxDoc());
               for(int i=0;i< reader.maxDoc();i++){ 
                    if(reader.document(i).get("name").enth("杂志"))//将以“杂志”后缀的过滤掉 
                        continue; 
                        bit.set(i);ks 
                     } 
               return bit; 
           } 
        }); 
        System.out.println(hits.length()); 
        for(int i=0;i< hits.length();i++){ 
            doc =hits.doc(i); 
            System.out.println(doc.get("name")); 
        } 
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: