您的位置:首页 > 其它

lucene学习之创建自定义排序

2015-05-06 18:25 323 查看
Lucene提供了一套强大的API来帮助我们实现自定义排序,本节我们使用一个距离搜索的例子来阐述:

其实核心是换一个comparator就成,而这个排序器用在哪里呢,如下所示:

package custom;

import java.io.IOException;

import org.apache.lucene.search.FieldComparator;
import org.apache.lucene.search.FieldComparatorSource;

public class DistanceComparatorSource extends FieldComparatorSource {
private  int x;
private int 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 {//lucene所跟踪的队列
return new DistanceSourceLookupComparHor(fieldname, num`
its,x,y);
}
}
package custom;

import java.io.IOException;

import org.apache.lucene.index.BinaryDocValues;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.search.SimpleFieldComparator;
import org.apache.lucene.util.BytesRef;

public class DistanceSourceLookupComparator extends
SimpleFieldComparator<String> {
private float[] values;
private float top;
private float bottom;
private String fieldName;

private int x;
private int y;

private BinaryDocValues binaryDocValues;

public DistanceSourceLookupComparator(String fieldName, int numHits, int x,
int y) {
values = new float[numHits];
this.fieldName = fieldName;
this.x = x;
this.y = y;
}

@Override
public int compare(int slot1, int slot2) {
if (values[slot1] > values[slot2]) {
return 1;
}
if (values[slot1] < values[slot2]) {
return -1;
}
return 0;
}

private float getDistance(int doc) {
BytesRef bytesRef = binaryDocValues.get(doc);
String xy = bytesRef.utf8ToString();
String[] array = xy.split(",");
int deltax = Integer.parseInt(array[0]) - x;
int deltay = Integer.parseInt(array[1]) - y;
float distance = (float) Math.sqrt(deltax * deltax + deltay * deltay);
//System.out.println(distance);
return distance;
}

@Override
protected void doSetNextReader(LeafReaderContext context)
throws IOException {
binaryDocValues = context.reader().getBinaryDocValues(fieldName);
}

public void setBottom(int slot) {
bottom = values[slot];
}//设置底部slot

public int compareBottom(int doc) throws IOException {//与队列中命中结果评分最低的比较
float distance = getDistance(doc);
if (bottom < distance) {
return -1;
}
if (bottom > distance) {
return 1;
}
return 0;
}

public int compareTop(int doc) throws IOException {
float distance = getDistance(doc);
if (top < distance) {
return -1;
}
if (top > distance) {
return 1;
}
return 0;
}

public void copy(int slot, int doc) throws IOException {//新的命中结果拷贝至队列中
values[slot] = getDistance(doc);
}

@Override
public void setTopValue(String value) {
top = Float.valueOf(value);
}

@Override
public String value(int slot) {//
return values[slot] + "";
}
}
package custom;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.BinaryDocValuesField;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.IndexWriterConfig.OpenMode;
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.TopFieldDocs;
import org.apache.lucene.store.RAMDirectory;
import org.apache.lucene.util.BytesRef;

public class CustomSortTest {
public static void main(String[] args) throws Exception {
RAMDirectory directory = new RAMDirectory();
Analyzer analyzer = new StandardAnalyzer();
IndexWriterConfig indexWriterConfig = new IndexWriterConfig(analyzer);
indexWriterConfig.setOpenMode(OpenMode.CREATE_OR_APPEND);
IndexWriter indexWriter = new IndexWriter(directory, indexWriterConfig);
addPoint(indexWriter, "El charro", "restaurant", 1, 2);
addPoint(indexWriter, "Cafe Poca Cosa", "restaurant", 5, 9);
addPoint(indexWriter, "Los Betos", "restaurant", 9, 6);
addPoint(indexWriter, "Nico's Toco Shop", "restaurant", 3, 8);
indexWriter.close();

IndexReader reader = DirectoryReader.open(directory);
IndexSearcher searcher = new IndexSearcher(reader);
Query query = new TermQuery(new Term("type","restaurant"));
//使用重载后的排序类构造函数
Sort sort = new Sort(new SortField("location",new DistanceComparatorSource(10, 10)));
TopFieldDocs topDocs = searcher.search(query, null, Integer.MAX_VALUE,sort,true,false);
ScoreDoc[] docs = topDocs.scoreDocs;
for(ScoreDoc doc : docs){
Document document = searcher.doc(doc.doc);
System.out.println(document.get("name") + ":" + doc.score);
}
}

private static void addPoint(IndexWriter writer,String name,String type,int x,int y) throws Exception{
Document document = new Document();
String xy = x + "," + y;
document.add(new Field("name",name,Field.Store.YES,Field.Index.NOT_ANALYZED));
document.add(new Field("type",type,Field.Store.YES,Field.Index.NOT_ANALYZED));
document.add(new Field("location",xy,Field.Store.YES,Field.Index.NOT_ANALYZED));
document.add(new BinaryDocValuesField("location", new BytesRef(xy.getBytes())));
writer.addDocument(document);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: