<div class="iteye-blog-content-contain" style="font-size: 14px">
测试类
package sort.distanceSort;
import java.io.IOException;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field.Store;
import org.apache.lucene.document.IntField;
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.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.store.RAMDirectory;
import org.apache.lucene.util.Version;
/**
* @author
* @Description TODO
*/
public class DistanceSortingTest{
private RAMDirectory directory;
private IndexSearcher searcher;
private Query query;
public void setUp() throws IOException{
directory=new RAMDirectory();
IndexWriter writer=new IndexWriter(directory,
new IndexWriterConfig(Version.LUCENE_43,
new StandardAnalyzer(Version.LUCENE_43)));
addPoint(writer, "El", "Charro", 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);
addPoint(writer, "Nico's Taco Shopa", "restaurant", 1, 8);
writer.close();
searcher=new IndexSearcher(DirectoryReader.open(directory));
query=new TermQuery(new Term("type","restaurant"));
System.out.println(query);
}
private void addPoint(IndexWriter writer,String name,String type,int x,int y )
throws IOException{
Document doc=new Document();
Store yes=Store.YES;
doc.add(new StringField("name", name, yes));
doc.add(new StringField("type", type, yes));
doc.add(new IntField("x", x, yes));
doc.add(new IntField("y", y, yes));
writer.addDocument(doc);
}
public void testNearestRestaurantToHome() throws IOException{
Sort sort=new Sort(new SortField("location", new DistanceComparatorSource(0, 0)));
TopDocs hits=searcher.search(query,10,sort);
ScoreDoc[] sds=hits.scoreDocs;
for(ScoreDoc sd:sds){
System.out.println( searcher.doc(sd.doc).get("name"));
}
}
public static void main(String[] args) throws IOException {
DistanceSortingTest d=new DistanceSortingTest();
d.setUp();
d.testNearestRestaurantToHome();
}
}
自定义排序类
package sort.distanceSort;
import java.io.IOException;
import org.apache.lucene.index.AtomicReaderContext;
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;
/**
* @author
* @Description TODO
*/
public class DistanceComparatorSource extends FieldComparatorSource{
private int x;
private int y;
public DistanceComparatorSource(int x,int y){
this.x=x;
this.y=y;
}
/* (non-Javadoc)
* @see org.apache.lucene.search.FieldComparatorSource#newComparator(java.lang.String, int, int, boolean)
*/
@Override
public FieldComparator<?> newComparator(String fieldName, int numHits,
int sortPos, boolean reversed) throws IOException {
// TODO Auto-generated method stub
return new DistanceScoreDocLookupComparator(fieldName, numHits);
}
private class DistanceScoreDocLookupComparator extends FieldComparator{
private Ints xDoc,yDoc;
private float[] value;
private float bottom;
String fieldName;
public DistanceScoreDocLookupComparator(String fidldName,int numHits){
value=new float[numHits];
this.fieldName=fidldName;
}
/* (non-Javadoc)
* 传入新的AtomicReaderContext 所有的后续的docIDs都会关联到当前的reader(
*如果您需要将其映射到一个顶级docID您必须添加docBase)
*context 当前reader的上下文环境
*Returns 比较器需要用到这个实例,大多数比较器都是返回当前实例,夸segment的重用当前实例
*
*/
@Override
public FieldComparator setNextReader(AtomicReaderContext context)
throws IOException {
xDoc=FieldCache.DEFAULT.getInts(context.reader(), "x", false);
yDoc=FieldCache.DEFAULT.getInts(context.reader(), "y", false);
return this;
}
@Override
public int compare(int slot1, int slot2) {
if(value[slot1]<value[slot2])return -1;
if(value[slot1]>value[slot2])return 1;
return 0;
}
/* (non-Javadoc)
* 设置 最底位置,即 进到对比队列中的最小值(排在末尾的);
*/
@Override
public void setBottom(int slot) {
bottom=value[slot];
}
/* (non-Javadoc)
* 与文档进行底部比对,只有在setBottom 之后才会调用,与 compare(int,int)功能相同
* 对于一次命中相对较多的搜索中,这个方法会成为一个调用热点。(是到目前为止调用最为频繁的一个方法)
*/
@Override
public int compareBottom(int doc) throws IOException {
float docDistance=getDistance(doc);
if(bottom<docDistance)return -1;
if(bottom>docDistance)return 1;
return 0;
}
/* (non-Javadoc)
* 当一个命中结果具有争议性的时候会调用这个方法,你需要复制任何一个与文档相关的状态
* 在之后会再次比对,并放入指定的位置
*/
@Override
public void copy(int slot, int doc) throws IOException {
value[slot]=getDistance(doc);
}
public float getDistance(int doc){
int deltax=xDoc.get(doc)-x;
int deltay=yDoc.get(doc)-y;
return (float)Math.sqrt(deltax*deltax+deltay*deltay);
}
/* (non-Javadoc)
* 返回当前位置的实际值
*/
@Override
public Object value(int slot) {
return Float.valueOf(value[slot]);
}
/* (non-Javadoc)
* 如果 doc的值小于给定值返回负数
*/
@Override
public int compareDocToValue(int doc, Object value) throws IOException {
return 0;
}
}
}
</div>