# 一步一步跟我学习lucene（13）---lucene搜索之自定义排序的实现原理和编写自己的自定义排序工具

19 篇文章 22 订阅

## IntComparator相关实现

IntComparator声明的参数为：

private final int[] values;
private int bottom;                           // Value of bottom of queue
private int topValue;

• values随着类初始化而初始化其长度
• values用于存储NumericDocValues中读取到的内容

values的初始化

/**
* Creates a new comparator based on {@link Integer#compare} for {@code numHits}.
* When a document has no value for the field, {@code missingValue} is substituted.
*/
public IntComparator(int numHits, String field, Integer missingValue) {
super(field, missingValue);
values = new int[numHits];
}

values值填充(此为IntComparator的处理方式)

 @Override
public void copy(int slot, int doc) {
// Test for v2 == 0 to save Bits.get method call for
// the common case (doc has value and value is non-zero):
if (docsWithField != null && v2 == 0 && !docsWithField.get(doc)) {
v2 = missingValue;
}

values[slot] = v2;
}

    @Override
public int compare(int slot1, int slot2) {
return Integer.compare(values[slot1], values[slot2]);
}

@Override
public int compareBottom(int doc) {
// Test for v2 == 0 to save Bits.get method call for
// the common case (doc has value and value is non-zero):
if (docsWithField != null && v2 == 0 && !docsWithField.get(doc)) {
v2 = missingValue;
}

return Integer.compare(bottom, v2);
}
    @Override
public int compareTop(int doc) {
// Test for docValue == 0 to save Bits.get method call for
// the common case (doc has value and value is non-zero):
if (docsWithField != null && docValue == 0 && !docsWithField.get(doc)) {
docValue = missingValue;
}
return Integer.compare(topValue, docValue);
}

## 实现自己的FieldComparator

package com.lucene.search;

import java.io.IOException;

import org.apache.lucene.index.BinaryDocValues;
import org.apache.lucene.index.DocValues;
import org.apache.lucene.search.SimpleFieldComparator;

import com.lucene.util.ObjectUtil;

/**自定义comparator
* @author lenovo
*
*/
public class SelfDefineComparator extends SimpleFieldComparator<String> {
private Object[] values;//定义的Object[]，同IntComparator
private Object bottom;
private Object top;
private String field;
private BinaryDocValues binaryDocValues;//接收的BinaryDocValues,同IntComparator中的NumericDocValues
private ObjectUtil objectUtil;//这里为了便于拓展用接口代替抽象类
private Object[] params;//接收的参数

public SelfDefineComparator(String field, int numHits, Object[] params,ObjectUtil objectUtil) {
values = new Object[numHits];
this.objectUtil = objectUtil;
this.field = field;
this.params = params;
}

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

@Override
public int compareBottom(int doc) throws IOException {
Object distance = getValues(doc);
return (bottom.toString()).compareTo(distance.toString());
}

@Override
public int compareTop(int doc) throws IOException {
Object distance = getValues(doc);
return objectUtil.compareTo(top,distance);
}

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

/**��ȡdocID��Ӧ��value
* @param doc
* @return
*/
private Object getValues(int doc) {
Object instance = objectUtil.getValues(doc,params,binaryDocValues) ;
return instance;
}

@Override
throws IOException {
}

@Override
public int compare(int slot1, int slot2) {
return objectUtil.compareTo(values[slot1],values[slot2]);
}
@Override
public void setTopValue(String value) {
this.top = value;
}

@Override
public String value(int slot) {
return values[slot].toString();
}

}


ObjectUtil接口定义如下：

package com.lucene.util;

import org.apache.lucene.index.BinaryDocValues;

public interface ObjectUtil {

/**自定义的获取处理值的方法
* @param doc
* @param params
* @param binaryDocValues
* @return
*/
public abstract Object getValues(int doc, Object[] params, BinaryDocValues binaryDocValues) ;

/**compare比较器实现
* @param object
* @param object2
* @return
*/
public abstract int compareTo(Object object, Object object2);

}


package com.lucene.search;

import java.io.IOException;

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

import com.lucene.util.ObjectUtil;

/**comparator用于接收用户原始输入，继承自FieldComparatorSource实现了自定义comparator的构建
* @author lenovo
*
*/
public class SelfDefineComparatorSource extends FieldComparatorSource {
private Object[] params;//接收的参数
private ObjectUtil objectUtil;//这里为了便于拓展用接口代替抽象类

public Object[] getParams() {
return params;
}

public void setParams(Object[] params) {
this.params = params;
}

public ObjectUtil getObjectUtil() {
return objectUtil;
}

public void setObjectUtil(ObjectUtil objectUtil) {
this.objectUtil = objectUtil;
}

public SelfDefineComparatorSource(Object[] params, ObjectUtil objectUtil) {
super();
this.params = params;
this.objectUtil = objectUtil;
}

@Override
public FieldComparator<?> newComparator(String fieldname, int numHits,
int sortPos, boolean reversed) throws IOException {
//实际比较由SelfDefineComparator实现
return new SelfDefineComparator(fieldname, numHits, params, objectUtil);
}
}


package com.lucene.search;

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.document.StringField;
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.MatchAllDocsQuery;
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.BytesRef;

import com.lucene.util.CustomerUtil;
import com.lucene.util.ObjectUtil;
import com.lucene.util.StringComparaUtil;

/**
*
* @author 吴莹桂
*
*/
public class SortTest {
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);
indexWriter.commit();
indexWriter.close();
Query query = new MatchAllDocsQuery();
ObjectUtil util = new StringComparaUtil();
Sort sort = new Sort(new SortField("name",new SelfDefineComparatorSource(new Object[]{},util),true));
TopDocs topDocs = searcher.search(query, Integer.MAX_VALUE, sort);
ScoreDoc[] docs = topDocs.scoreDocs;
for(ScoreDoc doc : docs){
Document document = searcher.doc(doc.doc);
System.out.println(document.get("name"));
}
}

private static void addDocument(IndexWriter writer,String name) throws Exception{
Document document = new Document();
}
}


package com.lucene.util;

import org.apache.lucene.index.BinaryDocValues;
import org.apache.lucene.util.BytesRef;

public class StringComparaUtil implements ObjectUtil {

@Override
public Object getValues(int doc, Object[] params,
BinaryDocValues binaryDocValues) {
BytesRef bytesRef = binaryDocValues.get(doc);
String value = bytesRef.utf8ToString();
return value;
}

@Override
public int compareTo(Object object, Object object2) {
// TODO Auto-generated method stub
return object.toString().compareTo(object2.toString());
}

}


08-22 2971
05-24
09-17 1377
10-05 1016
06-10 63
11-06 49
11-28 268
08-25 1335
01-29 1229
11-18 49
05-06 1061
12-15 737
04-28 124
01-30 1387
12-14 5252
12-15 163
05-16 5426

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

• 非常没帮助
• 没帮助
• 一般
• 有帮助
• 非常有帮助

javageekcoder

¥2 ¥4 ¥6 ¥10 ¥20

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