关于lucene自定义排序 FieldComparatorSource

其实关于FieldComparatorSource的lucene默认实现,应该已经满足我们对结果排序的需求了,比如:
[img]http://dl.iteye.com/upload/attachment/550152/6f040161-2ed2-3b9c-9a0c-3bccab11f6b5.jpg[/img]
如果我们希望对搜索结果按照一定的业务规则,人工干预排序,不妨尝试一下继承一下FieldComparatorSource以及实现FieldComparator类。
以下是一个用户期望根据用户登录Ip对应的城市的相应数据排在最前面。
创建索引:

/**
* 创建place索引
*/
public static void createPlaceIndex(){
Analyzer analyzer = new IKAnalyzer();
PerFieldAnalyzerWrapper perFieldAnalyzerWrapper = new PerFieldAnalyzerWrapper(analyzer);
try {

//perFieldAnalyzerWrapper.addAnalyzer("price", new WhitespaceAnalyzer());
IndexWriter writer = new IndexWriter(FSDirectory.open(new File(index_path5)), perFieldAnalyzerWrapper, true,IndexWriter.MaxFieldLength.LIMITED);
Document doc = new Document();

doc.add(new Field("placeName", "杭州西湖 测试开发", Field.Store.YES, Field.Index.ANALYZED));
doc.add(new Field("placeName2", "杭州西湖 测试开发", Field.Store.YES, Field.Index.NOT_ANALYZED));
writer.addDocument(doc);
doc = new Document();
doc.add(new Field("placeName", "西湖 九天", Field.Store.YES, Field.Index.ANALYZED));
doc.add(new Field("placeName2", "西湖 九天", Field.Store.YES, Field.Index.NOT_ANALYZED));
writer.addDocument(doc);
doc = new Document();
doc.add(new Field("placeName", "扬州廋西湖 高级开发", Field.Store.YES, Field.Index.ANALYZED));
doc.add(new Field("placeName2", "扬州廋西湖 高级开发", Field.Store.YES, Field.Index.NOT_ANALYZED));
writer.addDocument(doc);
doc = new Document();
doc.add(new Field("placeName", "苏州西湖", Field.Store.YES, Field.Index.ANALYZED));
doc.add(new Field("placeName2", "苏州西湖", Field.Store.YES, Field.Index.NOT_ANALYZED));
writer.addDocument(doc);



writer.close();

} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}

实现Comparator以及ComparatorSource

class PlaceNameSortComparatorSource extends FieldComparatorSource {
private String userLocation ;
public PlaceNameSortComparatorSource(String userLocation ){
this.userLocation = userLocation;
}
@Override
public FieldComparator newComparator(String fieldname, int numHits,
int sortPos, boolean reversed) throws IOException {
// TODO Auto-generated method stub
return new PlaceComparator(numHits,fieldname,userLocation);
}

}


final class PlaceComparator extends FieldComparator {
private final String[] values;
private String[] currentReaderValues;
private final String field;
private String bottom;
private String userLocation;


PlaceComparator(int numHits, String field, String userLocation) {
values = new String[numHits];
this.field = field;
this.userLocation = userLocation;
}

@Override
public int compare(int slot1, int slot2) {

int cmpValue=0;
final String v1 = values[slot1];
final String v2 = values[slot2];

if(v1.indexOf(userLocation) !=-1){
cmpValue= -999999999;
}
if(v2.indexOf(userLocation) !=-1){
cmpValue= -999999999;
}else{
cmpValue = 999999999;
}

System.out.println(slot1+"-"+slot2);
System.out.println(v1+"-"+v2);
System.out.println("cmpValue="+cmpValue);
return cmpValue;
}

@Override
public int compareBottom(int doc) {
final String v2 = currentReaderValues[doc];
if(v2.indexOf(userLocation) !=-1){
return -999999999;
}
if(bottom.indexOf(userLocation)!=-1){
return -999999999;
}
return bottom.compareTo(v2);
}

@Override
public void copy(int slot, int doc) {
values[slot] = currentReaderValues[doc];
}

@Override
public void setNextReader(IndexReader reader, int docBase) throws IOException {
currentReaderValues = FieldCache.DEFAULT.getStrings(reader, field);
}

@Override
public void setBottom(final int bottom) {
this.bottom = values[bottom];
}

@Override
public Comparable value(int slot) {
return values[slot];
}

}


搜索测试:

Query trquery = new PrefixQuery(new Term("placeName","西湖" ));
BooleanQuery booleanQuery = new BooleanQuery();
TermQuery tq = new TermQuery(new Term("placeName","西湖"));

IndexReader indexReader = IndexReader.open(FSDirectory.open(new File(index_path5)));
SortField sortField = new SortField("placeName2", new PlaceNameSortComparatorSource("扬州"),true );
Sort sort = new Sort();
sort.setSort(sortField);

Searcher searcher = new IndexSearcher(indexReader);

TopDocs topDocs = searcher.search(tq,null,100,sort);

for (ScoreDoc hits:topDocs.scoreDocs){
Document doc = searcher.doc(hits.doc);
System.out.println("doc = "+doc.get("placeName"));
}


运行结果:
doc = 扬州廋西湖 高级开发
doc = 西湖 九天
doc = 苏州西湖
doc = 杭州西湖 测试开发
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值