lucene4.3 自定义排序

       今日在学习lucene,参考书籍是lucene in action,但因为lucene 版本更新很快,此书中很多地方因api的变动而使得我在测试代码例子的时候时常出现错误,而网上对lucene4.3的介绍也很少。今天在学习第六章 对搜索结果自定义排序时,发现FieldComparator基类的method有变动,测试很久,终于绕回来了。

以下是自定义排序代码:

package org.lucene.custom;
import java.io.IOException;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.AtomicReaderContext;
import org.apache.lucene.index.BinaryDocValues;
import org.apache.lucene.search.FieldCache;
import org.apache.lucene.search.FieldCache.Ints;
import org.apache.lucene.search.FieldComparator;
import org.apache.lucene.search.FieldComparatorSource;
import org.apache.lucene.util.BytesRef;


public class DistanceComparatorSource extends FieldComparatorSource {

private int x,y;
public DistanceComparatorSource(int x,int y)
{
this.x=x;
this.y =y;
}
@Override
public FieldComparator newComparator(String fieldname, int numHits,
int sortPos, boolean reversed) throws IOException {

return new DistanceScoreDocLookupComparator(fieldname, numHits);
}
private class DistanceScoreDocLookupComparator extends FieldComparator{
private int[] xDoc,yDoc;
private float[] values;
private float bottom;
String fieldName;
public DistanceScoreDocLookupComparator(String fieldName,int numHits)throws IOException{
values = new float[numHits];
this.fieldName = fieldName;
}
@Override
public int compare(int slot1, int slot2) {
if(values[slot1]<values[slot2]) return -1;
if(values[slot1]>values[slot2]) return 1;
return 0;

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

@Override
public int compareBottom(int doc) throws IOException {
float docDistance = getDistance(doc);
if(bottom<docDistance) return -1;
if(bottom>docDistance) return 1;

return 0;
}


private float getDistance(int doc) {
int deltax=xDoc[doc]-x;
int deltay=yDoc[doc]-y;
return (float)Math.sqrt(deltax*deltax+deltay*deltay);
}
@Override
public void copy(int slot, int doc) throws IOException {
values[slot]=getDistance(doc);
}

@Override
public FieldComparator setNextReader(AtomicReaderContext context)   
throws IOException {
BinaryDocValues bdv=FieldCache.DEFAULT.getTerms(context.reader(),this.fieldName);//主要是此处做了变动,之前我们可以通过FieldCache.DEFAULT.getString() 获得cache里的document value
int length=context.reader().maxDoc();
xDoc = new int[length];
yDoc = new int[length];
for(int i=0;i<length;i++)
{ 
BytesRef br=new BytesRef();
bdv.get(i,br);
String result=br.utf8ToString();
String[] s=result.split(",");
xDoc[i]=Integer.parseInt(s[0]);
yDoc[i]=Integer.parseInt(s[1]);
}

return this;
}


@Override
public Object value(int slot) {
return new Float(values[slot]);
}


@Override
public int compareDocToValue(int doc, Object value) throws IOException {
if(doc<((Integer)value)) return -1;
if(doc>((Integer)value)) return 1;
return 0;
}

}
public String toString(){
return "Distance from ("+x+","+y+")";
}
}


以下是测试demo:

package org.lucene.custom;
import java.io.IOException;
import junit.framework.TestCase;
import org.apache.lucene.analysis.core.WhitespaceAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.StringField;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.FieldDoc;
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.TermQuery;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.search.TopFieldDocs;
import org.apache.lucene.store.RAMDirectory;
import org.apache.lucene.util.Version;


public class DistanceSortingTest extends TestCase {
private RAMDirectory directory;
private IndexSearcher searcher;
private Query query;

protected void setUp()throws Exception {
directory =new RAMDirectory();
IndexWriterConfig config= new IndexWriterConfig(Version.LUCENE_43,
new WhitespaceAnalyzer(Version.LUCENE_43));
IndexWriter writer=
new IndexWriter(directory,config);
addPoint(writer, "El Charro", "restaurant", 1, 2);
addPoint(writer, "Cafe Poca Cosa", "restaurant", 5, 9);
addPoint(writer, "Los Betos", "restaurant", 9,6);
addPoint(writer, "Nico's Taco Shop", "restaurant", 3,8);

writer.close();
searcher = new IndexSearcher(DirectoryReader.open(directory));
query=new TermQuery(new Term("type","restaurant"));

}
private void addPoint(IndexWriter writer,String name,String type,int x ,int y)throws IOException{
Document doc=new Document();
doc.add(new Field("name",name,StringField.TYPE_STORED));
doc.add(new Field("type",type,StringField.TYPE_STORED));
doc.add(new Field("location",x+","+y,StringField.TYPE_STORED));
writer.addDocument(doc);

}

public void testNearestRestaurantToHome() throws Exception{
Sort sort = new Sort(new SortField("location",new DistanceComparatorSource(3,6)));

TopDocs hits = searcher.search(query, null,10,sort);
for(ScoreDoc sd:hits.scoreDocs)
{
int docID=sd.doc;
Document doc = searcher.doc(docID);
System.out.println(doc.get("name")+":"+doc.get("location"));
}
assertEquals("closest", "El Charro",searcher.doc(hits.scoreDocs[0].doc).get("name"));
assertEquals("furthest", "Los Betos",searcher.doc(hits.scoreDocs[3].doc).get("name"));
}


菜鸟初学lucene,不对之处,请多指教。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值