Lucene排序以及自定义排序

本文介绍如何使用Lucene进行全文检索并实现排序功能,包括代码示例及自定义排序算法的方法。

现在开发搜索系统,使用的是开源界比较推崇的Lucene,版本是Maven库上面的3.5,这个版本里面有很多方法都不建议使用了。所以代码创建的方式有那么点变化,我使用的分词器是IkAnalyzer。Lucene全文检索的功能是很强大的,我们在做电子商务系统的时候肯定是会遇到排序的问题,比如销量,比如价格等等,为了方便客户我们便需要Lucene的排序功能,其实Lucene中的排序很简单也很方便,我们在创建搜索器的时候增加一个Sort 就行了,Sort的构造函数需要SortField,具体大家可以去参考Lucene的源代码,我下面写了一个简单的例子来演示怎么使用。代码如下:

Java代码 复制代码  收藏代码
  1. import java.io.IOException;   
  2. import java.util.Locale;   
  3. import org.apache.lucene.analysis.Analyzer;   
  4. import org.apache.lucene.document.Document;   
  5. import org.apache.lucene.document.Field;   
  6. import org.apache.lucene.document.Field.Index;   
  7. import org.apache.lucene.document.Field.Store;   
  8. import org.apache.lucene.index.IndexReader;   
  9. import org.apache.lucene.index.IndexWriter;   
  10. import org.apache.lucene.index.IndexWriterConfig;   
  11. import org.apache.lucene.search.FieldComparator;   
  12. import org.apache.lucene.search.FieldComparatorSource;   
  13. import org.apache.lucene.search.IndexSearcher;   
  14. import org.apache.lucene.search.Query;   
  15. import org.apache.lucene.search.ScoreDoc;   
  16. import org.apache.lucene.search.Sort;   
  17. import org.apache.lucene.search.SortField;   
  18. import org.apache.lucene.search.TopDocs;   
  19. import org.apache.lucene.store.RAMDirectory;   
  20. import org.apache.lucene.util.Version;   
  21. import org.junit.Test;   
  22. import org.wltea.analyzer.lucene.IKAnalyzer;   
  23. import org.wltea.analyzer.lucene.IKQueryParser;   
  24. import org.wltea.analyzer.lucene.IKSimilarity;   
  25. public class LuceneSortTest {   
  26.     /**  
  27.      * Lucene排序查询  
  28.      */  
  29.     @Test  
  30.     public void testSort() throws Exception{   
  31.         String name = "name";   
  32.         String field = "price";   
  33.         String names[] = {"衣服","睡衣","漂亮衣服","好看衣服","男士衣服","女士衣服"};   
  34.         double price[] = {12.0,13.0,8.8,9.6,7.5,12.1};   
  35.         RAMDirectory dir = new RAMDirectory();   
  36.         Analyzer analyzer = new IKAnalyzer();   
  37.         IndexWriterConfig cfg = new IndexWriterConfig(Version.LUCENE_35, analyzer);   
  38.         IndexWriter writer = new IndexWriter(dir, cfg);   
  39.         for (int i=0;i<names.length;i++) {   
  40.             Document doc = new Document();   
  41.             doc.add(new Field(name, names[i], Store.YES, Index.ANALYZED));   
  42.             doc.add(new Field(field, String.valueOf(price[i]), Store.YES, Index.NOT_ANALYZED));   
  43.             writer.addDocument(doc);   
  44.         }   
  45.         writer.commit();   
  46.         writer.close();   
  47.         IndexReader reader = IndexReader.open(dir);   
  48.         Query query = IKQueryParser.parse(name, "衣服");   
  49.         Sort sort = new Sort(new SortField(field,SortField.DOUBLE,true)); //排序 false 升序 true降序   
  50.         IndexSearcher isearcher = new IndexSearcher(reader);   
  51.         isearcher.setSimilarity(new IKSimilarity());   
  52.         TopDocs topDocs =  isearcher.search(query, 5, sort);   
  53.         ScoreDoc scoreDocs[] = topDocs.scoreDocs;   
  54.         for (ScoreDoc scoreDoc : scoreDocs) {   
  55.             Document doc =  isearcher.doc(scoreDoc.doc);   
  56.             System.out.println(doc.get(field));   
  57.         }   
  58.         isearcher.close();   
  59.         dir.close();   
  60.     }   
  61. }  
import java.io.IOException;
import java.util.Locale;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.Field.Index;
import org.apache.lucene.document.Field.Store;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.search.FieldComparator;
import org.apache.lucene.search.FieldComparatorSource;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.Sort;
import org.apache.lucene.search.SortField;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.RAMDirectory;
import org.apache.lucene.util.Version;
import org.junit.Test;
import org.wltea.analyzer.lucene.IKAnalyzer;
import org.wltea.analyzer.lucene.IKQueryParser;
import org.wltea.analyzer.lucene.IKSimilarity;
public class LuceneSortTest {
	/**
	 * Lucene排序查询
	 */
	@Test
	public void testSort() throws Exception{
		String name = "name";
		String field = "price";
		String names[] = {"衣服","睡衣","漂亮衣服","好看衣服","男士衣服","女士衣服"};
		double price[] = {12.0,13.0,8.8,9.6,7.5,12.1};
		RAMDirectory dir = new RAMDirectory();
		Analyzer analyzer = new IKAnalyzer();
		IndexWriterConfig cfg = new IndexWriterConfig(Version.LUCENE_35, analyzer);
		IndexWriter writer = new IndexWriter(dir, cfg);
		for (int i=0;i<names.length;i++) {
			Document doc = new Document();
			doc.add(new Field(name, names[i], Store.YES, Index.ANALYZED));
			doc.add(new Field(field, String.valueOf(price[i]), Store.YES, Index.NOT_ANALYZED));
			writer.addDocument(doc);
		}
		writer.commit();
		writer.close();
		IndexReader reader = IndexReader.open(dir);
		Query query = IKQueryParser.parse(name, "衣服");
		Sort sort = new Sort(new SortField(field,SortField.DOUBLE,true)); //排序 false 升序 true降序
		IndexSearcher isearcher = new IndexSearcher(reader);
		isearcher.setSimilarity(new IKSimilarity());
		TopDocs topDocs =  isearcher.search(query, 5, sort);
		ScoreDoc scoreDocs[] = topDocs.scoreDocs;
		for (ScoreDoc scoreDoc : scoreDocs) {
			Document doc =  isearcher.doc(scoreDoc.doc);
			System.out.println(doc.get(field));
		}
		isearcher.close();
		dir.close();
	}
}

 

 

这段代码执行的结果为:

Java代码 复制代码  收藏代码
  1. 12.1  
  2. 12.0  
  3. 9.6  
  4. 8.8  
  5. 7.5  
12.1
12.0
9.6
8.8
7.5

 

 

在SortField里面有很多静态常量来提供给排序器作为排序的依据,Lucene里面自己定义好的排序实现已经基本能够满足我们的需求了,如果自己想定义一个自己的排序算法,那么可以继承FieldComparatorSource实现里面的方法:

 

Java代码 复制代码  收藏代码
  1. public FieldComparator newComparator(String fieldname, int numHits,   
  2.             int sortPos, boolean reversed) throws IOException {   
  3.         // TODO Auto-generated method stub   
  4.         return new DoubleFieldComparatorSource.DoubleFieldComparator();   
  5.     }  
public FieldComparator newComparator(String fieldname, int numHits,
			int sortPos, boolean reversed) throws IOException {
		// TODO Auto-generated method stub
		return new DoubleFieldComparatorSource.DoubleFieldComparator();
	}

 

里面的FieldComparator是一个抽象类,主要就是用来作比较使用的,定义自己的排序算法关键也在于继承这个抽象类,然后实现里面的方法,需要实现的方法如下:

 

Java代码 复制代码  收藏代码
  1. class DoubleFieldComparator extends FieldComparator{   
  2.         @Override  
  3.         public int compare(int slot1, int slot2) {   
  4.             return 0;   
  5.         }   
  6.         @Override  
  7.         public void setBottom(int slot) {   
  8.         }   
  9.         @Override  
  10.         public int compareBottom(int doc) throws IOException {   
  11.             return 0;   
  12.         }   
  13.         @Override  
  14.         public void copy(int slot, int doc) throws IOException {ub   
  15.         }   
  16.         @Override  
  17.         public void setNextReader(IndexReader reader, int docBase)   
  18.                 throws IOException {   
  19.         }   
  20.         @Override  
  21.         public Object value(int slot) {   
  22.             return null;   
  23.         }   
  24.     }  
class DoubleFieldComparator extends FieldComparator{
		@Override
		public int compare(int slot1, int slot2) {
			return 0;
		}
		@Override
		public void setBottom(int slot) {
		}
		@Override
		public int compareBottom(int doc) throws IOException {
			return 0;
		}
		@Override
		public void copy(int slot, int doc) throws IOException {ub
		}
		@Override
		public void setNextReader(IndexReader reader, int docBase)
				throws IOException {
		}
		@Override
		public Object value(int slot) {
			return null;
		}
	}

 

 

这里顺便列出Sort已经提供的比较值:

 

Java代码 复制代码  收藏代码
  1. SortField.SCORE 按积分排序   
  2. SortField.DOC 按文档排序   
  3. SortField.AUTO 域的值为intlongfloat都有效   
  4. SortField.STRING 域按STRING排序   
  5. SortField.FLOAT   
  6. SortField.LONG   
  7. SortField.DOUBLE   
  8. SortField.SHORT   
  9. SortField.CUSTOM 通过比较器排序   
  10. SortField.BYTE   
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值