【问题标题】:Lucene Returning Documents with non positive scoreLucene 以非正分数返回文档
【发布时间】:2015-10-27 06:08:00
【问题描述】:

我们最近升级了我们正在使用的 CMS,但不得不从 Lucene.net V2.3.1.301 到 V2.9.4.1

我们在原始解决方案中使用了 CustomScoreQuery,它执行了内置查询无法实现的各种过滤。 (GEO、多日期范围等)

自从从旧版本迁移到新版本的 Lucene 后,它开始返回文档,即使在我们检查结果时它们的得分为 0 甚至负数

以下是演示该问题的重构代码示例

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



    }

任何关于如何让 Lucene 不返回这些文档的建议都会很棒。 提前致谢。

【问题讨论】:

    标签: c# lucene sitecore lucene.net


    【解决方案1】:

    您可以编写一个自定义的Collector,它只收集具有&gt;0 分数的文档。然后将这个收集器的一个实例传递给Search() 方法。有这样一个Collectorhere的实现。

    但是,如果您不需要所有结果,documentation 建议不要使用此解决方案。可能是这种情况,因为您只选择前 1000 个文档。

    【讨论】:

      猜你喜欢
      • 2015-11-26
      • 1970-01-01
      • 2013-01-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-02
      • 1970-01-01
      相关资源
      最近更新 更多