c# - Lucene regresando documentos con puntaje no positivo
sitecore lucene.net (1)
Recientemente hemos actualizado un CMS en el que trabajamos y tuvimos que pasar de Lucene.net V2.3.1.301 a V2.9.4.1
Utilizamos una CustomScoreQuery en nuestra solución original que realizó varios filtros que no se pudieron lograr con las consultas integradas. (GEO, Multi Date Range, etc.)
Desde que pasó de la versión anterior a la nueva versión de Lucene, comenzó a devolver documentos a pesar de que tienen un puntaje de 0 o incluso negativo cuando inspeccionamos los resultados.
A continuación se muestra un ejemplo del código refatorado para demostrar el problema.
public LuceneTest()
{
Lucene.Net.Store.Directory luceneIndexDirectory = FSDirectory.Open(new System.IO.DirectoryInfo(@"C:/inetpub/wwwroot/Project/build/Data/indexes/all_site_search_en"));
Analyzer analyzer = new WhitespaceAnalyzer();
IndexSearcher searcher = new IndexSearcher(luceneIndexDirectory, true);
QueryParser parser = new QueryParser(Lucene.Net.Util.Version.LUCENE_23, "", analyzer);
parser.SetAllowLeadingWildcard(true);
Query dateQuery = ComposeEventDateQuery(new DateTime(2015, 11, 23), new DateTime(2015,11,25), searcher);
BooleanQuery combinedQuery = new BooleanQuery();
BooleanQuery.SetMaxClauseCount(10000);
combinedQuery.Add(dateQuery, BooleanClause.Occur.MUST);
TopDocs hitsFound = searcher.Search(dateQuery, 1000);
System.Console.WriteLine(String.Format("Found {0} matches with the date filters", hitsFound.TotalHits));
System.Console.ReadKey();
}
public static Query ComposeEventDateQuery(DateTime fromDate, DateTime ToDate, IndexSearcher MySearcher)
{
BooleanQuery query = new BooleanQuery();
Query boolQuery3A = new TermQuery(new Lucene.Net.Index.Term("_language", "en"));
Query eventDateQuery = new EventDateQuery1(boolQuery3A, MySearcher, fromDate, ToDate, false);
query.Add(eventDateQuery, BooleanClause.Occur.MUST);
return query;
}
public class EventDateQuery1 : CustomScoreQuery
{
private Searcher _searcher;
private DateTime _fromDT;
private DateTime _toDT;
private readonly string _dateFormat = "yyyyMMdd";
private bool _shouldMatchNonEvents = true;
public EventDateQuery1(Query subQuery, Searcher searcher, DateTime fromDT, bool shouldMatchNonEvents, int dateRange = 14)
: base(subQuery)
{
_searcher = searcher;
_fromDT = fromDT.Date;
_toDT = fromDT.AddDays(dateRange).Date;
_shouldMatchNonEvents = shouldMatchNonEvents;
}
public EventDateQuery1(Query subQuery, Searcher searcher, DateTime fromDT, DateTime toDT, bool shouldMatchNonEvents)
: base(subQuery)
{
_searcher = searcher;
_fromDT = fromDT.Date;
_toDT = toDT.Date;
_shouldMatchNonEvents = shouldMatchNonEvents;
}
public override string ToString()
{
return GenerateUniqueKey();
}
public override string ToString(string field)
{
return GenerateUniqueKey();
}
public override string Name()
{
return GenerateUniqueKey();
}
public string GenerateUniqueKey()
{
return String.Format("EventDateQuery_{0}_{1}_{2}", _fromDT.ToString(_dateFormat), _toDT.ToString(_dateFormat), _shouldMatchNonEvents.ToString());
}
protected override CustomScoreProvider GetCustomScoreProvider(IndexReader reader)
{
return new EventDateQueryCustomScoreProvider(reader, _fromDT, _toDT, _shouldMatchNonEvents);
}
}
public class EventDateQueryCustomScoreProvider : CustomScoreProvider
{
private DateTime _fromDT;
private DateTime _toDT;
private readonly string _dateFormat = "yyyyMMdd";
private bool _shouldMatchNonEvents = true;
private float NoMatchFloat = 0f;
private float MatchFloat = 1f;
public EventDateQueryCustomScoreProvider(IndexReader reader, DateTime fromDT, DateTime toDT, bool shouldMatchNonEvents)
: base(reader)
{
_fromDT = fromDT.Date;
_toDT = toDT.Date;
_shouldMatchNonEvents = shouldMatchNonEvents;
}
public override float CustomScore(int doc, float subQueryScore, float valSrcScore)
{
return myScore(doc);
}
public override float CustomScore(int doc, float subQueryScore, float[] valSrcScores)
{
return myScore(doc);
}
public float myScore(int doc)
{
//Below is a fake implementation just to prove the run
if (doc < 10)
{
return 1F;
}
else
{
return 0F;
}
}
}
Cualquier sugerencia sobre cómo hacer que Lucene no devuelva estos documentos sería genial. Gracias por adelantado.
Puede escribir un Collector
personalizado que recopile solo documentos con una puntuación >0
. Y luego pase una instancia de este colector al método Search()
. Hay una implementación de tal Collector
here .
Sin embargo, la documentation sugiere esta solución si no necesita todos los resultados. Este es probablemente el caso, ya que solo está seleccionando los primeros 1000 documentos.