package org.apache.lucene.search;
import java.io.IOException;
import java.util.Set;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.index.NumericDocValues;
import org.apache.solr.search.CitationLRUCache;
/**
* Finds papers that are cited by our search. And then adjusts the score so that
* papers with most value from the cited_read_boost field are up
*
*/
public class SecondOrderCollectorOperatorExpertsCiting extends AbstractSecondOrderCollector {
Set<String> fieldsToLoad;
protected String referenceField;
protected String[] uniqueIdField;
protected String boostField;
private SolrCacheWrapper<CitationLRUCache<Object, Integer>> cache;
private LuceneCacheWrapper<NumericDocValues> boostCache;
private int hashCode;
public SecondOrderCollectorOperatorExpertsCiting(
SolrCacheWrapper<CitationLRUCache<Object, Integer>> cache,
LuceneCacheWrapper<NumericDocValues> boostWrapper) {
super();
assert cache != null;
this.cache = cache;
this.boostCache = boostWrapper;
setFinalValueType(FinalValueType.AGRESTI_COULL);
}
@Override
public void collect(int doc) throws IOException {
// find references froum our doc
int[] references = cache.getLuceneDocIds(doc+docBase);
if (references == null) {
return;
}
//Document document = reader.document(doc, fieldsToLoad);
float s = 0.5f; // lucene score doesn't make sense for us;
/*
// naive implementation (probably slow)
// IndexableField bf = document.getField(boostField);
if (bf != null) {
s = s + (s * bf.numericValue().floatValue());
}
else {
// penalize docs without boost
s = s * 0.8f;
}
*/
//if (bf==null) throw new IOException("Every document must have field: " + boostField);
// TODO: we must find the proper values for this, that means to compute the statistics
// (find the local minimas, maximas) for this function; this is just guessing....
float bc = 0.0f;
if ((bc = boostCache.getFloat(doc+docBase)) > 0.0f) {
s = s + bc;
}
//s = s / (vals.length + 100); // this would contribute only a part of the score to each citation
for (int docid: references) {
if (docid > 0) {
//System.out.println("expert: doc=" + (doc+docBase) + "(score:" + s + ") adding=" + docid + " (score:" + (s + boostCache[docid]) + ")" + " freq=" + references.length) ;
hits.add(new CollectorDoc(docid, s + boostCache.getFloat(docid), -1, 1));
}
}
}
@Override
public void doSetNextReader(LeafReaderContext context)
throws IOException {
this.docBase = context.docBase;
}
@Override
public String toString() {
return this.getClass().getSimpleName() + "(cache=" + cache.toString() + ", boost=" + boostCache.toString() + ")";
}
/** Returns a hash code value for this object. */
public int hashCode() {
if (hashCode == 0) {
hashCode = computeHashCode();
assert hashCode != 0;
}
assert hashCode == computeHashCode();
return hashCode;
}
private int computeHashCode() {
if (boostField != null)
return 1301081 ^ boostField.hashCode() ^ cache.hashCode();
return 1301081 ^ cache.hashCode();
}
@Override
public boolean needsScores() {
return true;
}
}