package org.apache.lucene.search;
import java.io.IOException;
import java.util.List;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.index.NumericDocValues;
/**
* This is a toy example for testing the ADS Classic relevance
* computtation. I know it is most likely inefficient and most
* likely it relies on a boost factor that needs more work,
* nevertheless a test can be done...
*
* ADS Classic score is implemented as
*
* ADS = (0.5 * norm(LS)) + (0.5 x cite_read_boost)
*
* where norm(LS) = normalized score (in this case it will be a Lucene
* score, normalized to be in the range 1-0, where
* 1 = the first, best hit; LS/MaximumLuceneScore
*
* cite_read_boost = score computed independently, it ranges 1-0,
* and I think the formula was st like:
*
* crb = citations * normalized(reads)
*
*/
public class SecondOrderCollectorAdsClassicScoringFormula extends AbstractSecondOrderCollector {
private String boostField;
private float highestLuceneScore;
private float lucenePart;
private float adsPart;
private CacheWrapper cache;
private LuceneCacheWrapper<NumericDocValues> boostCache;
public SecondOrderCollectorAdsClassicScoringFormula(SolrCacheWrapper cache, LuceneCacheWrapper<NumericDocValues> boostCache, float ratio) {
this.cache = cache;
this.lucenePart = ratio;
this.adsPart = 1.0f - ratio;
this.boostCache = boostCache;
}
public SecondOrderCollectorAdsClassicScoringFormula(CacheWrapper cache, LuceneCacheWrapper<NumericDocValues> boostCache) {
this.cache = cache;
this.lucenePart = 0.5f;
this.adsPart = 0.5f;
this.boostCache = boostCache;
}
@Override
public void setScorer(Scorer scorer) throws IOException {
this.scorer = scorer;
}
@Override
public void collect(int doc) throws IOException {
float s = scorer.score();
// we must collect everything and then we can normalize
// (we could be collecting only the x-first top hits,
// but this is a toy example....)
if (s > highestLuceneScore)
highestLuceneScore = s;
hits.add(new CollectorDoc(doc+docBase, s, -1, scorer.freq()));
}
@Override
public void doSetNextReader(LeafReaderContext context)
throws IOException {
this.docBase = context.docBase;
}
@Override
public List<CollectorDoc> getSubReaderResults(int rangeStart, int rangeEnd) {
if (hits.size() == 0)
return null;
lock.lock();
try {
if (!organized) {
for (CollectorDoc hit: hits) {
hit.score = (this.lucenePart * hit.score / highestLuceneScore) + (this.adsPart * getClassicBoostFactor(hit.doc));
}
}
}
finally {
lock.unlock();
}
return super.getSubReaderResults(rangeStart, rangeEnd);
}
private float getClassicBoostFactor(int doc) {
return boostCache.getFloat(doc);
}
@Override
public String toString() {
return this.getClass().getSimpleName() + "(cache=" + cache.toString() + ", boost=" + boostCache.toString()
+ ", lucene=" + this.lucenePart + ", adsPart=" + this.adsPart + ")";
}
@Override
public boolean needsScores() {
return true;
}
}