lucene学习之创建自定义排序

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);  
    }  
}

猜你喜欢

转载自blog.csdn.net/u014449866/article/details/45539055
今日推荐