. , . . .
public class CustomCollector extends TopDocsCollector<ScoreDocWithTime> {
ScoreDocWithTime pqTop;
public CustomCollector(int numHits) {
super(new HitQueueWithTime(numHits, true));
pqTop = pq.top();
}
@Override
public LeafCollector getLeafCollector(LeafReaderContext context)
throws IOException {
final int docBase = context.docBase;
final NumericDocValues modifiedDate =
DocValues.getNumeric(context.reader(), "modifiedDate");
return new LeafCollector() {
Scorer scorer;
@Override
public void setScorer(Scorer scorer) throws IOException {
this.scorer = scorer;
}
@Override
public void collect(int doc) throws IOException {
float score = scorer.score();
assert score != Float.NEGATIVE_INFINITY;
assert !Float.isNaN(score);
totalHits++;
if (score <= pqTop.score) {
return;
}
pqTop.doc = doc + docBase;
pqTop.score = score;
pqTop.timestamp = modifiedDate.get(doc);
pqTop = pq.updateTop();
}
};
}
@Override
public boolean needsScores() {
return true;
}
}
ScoreDoc
public class ScoreDocWithTime extends ScoreDoc {
public long timestamp;
public ScoreDocWithTime(long timestamp, int doc, float score) {
super(doc, score);
this.timestamp = timestamp;
}
public ScoreDocWithTime(long timestamp, int doc, float score, int shardIndex) {
super(doc, score, shardIndex);
this.timestamp = timestamp;
}
}
public class HitQueueWithTime extends PriorityQueue<ScoreDocWithTime> {
public HitQueueWithTime(int numHits, boolean b) {
super(numHits, b);
}
@Override
protected ScoreDocWithTime getSentinelObject() {
return new ScoreDocWithTime(0, Integer.MAX_VALUE, Float.NEGATIVE_INFINITY);
}
@Override
protected boolean lessThan(ScoreDocWithTime hitA, ScoreDocWithTime hitB) {
if (hitA.score == hitB.score)
return (hitA.timestamp == hitB.timestamp) ?
hitA.doc > hitB.doc :
hitA.timestamp < hitB.timestamp;
else
return hitA.score < hitB.score;
}
}
.
public class SearchTest {
public static void main(String[] args) throws IOException {
IndexWriterConfig indexWriterConfig = new IndexWriterConfig(new StandardAnalyzer());
Directory directory = new RAMDirectory();
IndexWriter indexWriter = new IndexWriter(directory, indexWriterConfig);
addDoc(indexWriter, "w1", 1000);
addDoc(indexWriter, "w1", 3000);
addDoc(indexWriter, "w1", 500);
addDoc(indexWriter, "w1 w2", 1000);
addDoc(indexWriter, "w1 w2", 3000);
addDoc(indexWriter, "w1 w2", 2000);
addDoc(indexWriter, "w1 w2", 5000);
final IndexReader indexReader = DirectoryReader.open(indexWriter, false);
IndexSearcher indexSearcher = new IndexSearcher(indexReader);
BooleanQuery query = new BooleanQuery();
query.add(new TermQuery(new Term("desc", "w1")), BooleanClause.Occur.SHOULD);
query.add(new TermQuery(new Term("desc", "w2")), BooleanClause.Occur.SHOULD);
CustomCollector results = new CustomCollector(100);
indexSearcher.search(query, results);
TopDocs search = results.topDocs();
for (ScoreDoc sd : search.scoreDocs) {
Document document = indexReader.document(sd.doc);
System.out.println(document.getField("desc").stringValue() + " " + ((ScoreDocWithTime) sd).timestamp);
}
}
private static void addDoc(IndexWriter indexWriter, String decs, long modifiedDate) throws IOException {
Document doc = new Document();
doc.add(new TextField("desc", decs, Field.Store.YES));
doc.add(new LongField("modifiedDate", modifiedDate, Field.Store.YES));
doc.add(new NumericDocValuesField("modifiedDate", modifiedDate));
indexWriter.addDocument(doc);
}
}
w1 w2 5000
w1 w2 3000
w1 w2 2000
w1 w2 1000
w1 3000
w1 1000
w1 500
P.S. Lucene 5.1