2015-10-27 16 views
17

Niedawno zmodernizowane CMS pracujemy nad i musiał przenieść się z Lucene.net V2.3.1.301 do V2.9.4.1Lucene Powracający Dokumenty z braku pozytywnego wyniku

Użyliśmy CustomScoreQuery w naszym egzemplarzu rozwiązanie, które dokonało różnych filtrów, których nie można było uzyskać za pomocą wbudowanych zapytań. (GEO, Multi Zakres dat itp)

Od momentu przeprowadzki ze starej wersji do nowej wersji Lucene zaczęło wracać do dokumentów, mimo że posiada 0 lub nawet ujemny wynik numeryczny kiedy sprawdzać wyniki

enter image description here poniżej znajduje się przykładowy kod refatored do wykazania WYDANIE

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; 
      } 
     } 



    } 

Wszelkie sugestie, w jaki sposób mają Lucene nie wrócić do tych dokumentów byłoby świetnie. Z góry dzięki.

Odpowiedz

6

Możesz napisać niestandardową Collector, która zbiera tylko dokumenty z wynikiem >0. Następnie przekaż instancję tego kolektora do metody Search(). Istnieje implementacja takiego Collectorhere.

Jednak, jeśli nie potrzebujesz wszystkich wyników, sugerujemy, aby documentation było przeciwko temu rozwiązaniu. Co prawdopodobnie ma miejsce, ponieważ wybierasz tylko 1000 najlepszych dokumentów.