C# Lucene返回非正面分数的文档

C# Lucene返回非正面分数的文档,c#,lucene,sitecore,lucene.net,C#,Lucene,Sitecore,Lucene.net,我们最近升级了一个CMS,我们的工作,并不得不从 Lucene.net V2.3.1.301至V2.9.4.1 我们在最初的解决方案中使用了CustomScoreQuery,它执行了内置查询无法实现的各种过滤。(地理位置、多日期范围等) 自从Lucene从旧版本迁移到新版本后,它开始返回文档,即使在我们检查结果时它们的分数为0甚至负数 下面是一个重构代码的示例来演示这个问题 public LuceneTest() { Lucene.Net.Store.Direc

我们最近升级了一个CMS,我们的工作,并不得不从 Lucene.net V2.3.1.301至V2.9.4.1

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

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



    }
public LuceneTest()
{
Lucene.Net.Store.Directory luceneIndexDirectory=FSDirectory.Open(new System.IO.DirectoryInfo(@“C:\inetpub\wwwroot\Project\build\Data\index\all\u site\u search\u en”);
Analyzer Analyzer=新的空白分析器();
IndexSearcher=newindexSearcher(luceneIndexDirectory,true);
QueryParser解析器=新的QueryParser(Lucene.Net.Util.Version.Lucene_23,“,analyzer);
setAllowReadingWildcard(true);
查询日期查询=ComposeEventDateQuery(新日期时间(2015,11,23),新日期时间(2015,11,25),搜索者);
BooleanQuery combinedQuery=新的BooleanQuery();
BooleanQuery.SetMaxClauseCount(10000);
combinedQuery.Add(dateQuery,BooleanClause.Occurse.MUST);
TopDocs hitsFound=searcher.Search(dateQuery,1000);
System.Console.WriteLine(String.Format(“发现{0}与日期过滤器匹配”,hitsFound.TotalHits));
System.Console.ReadKey();
}
公共静态查询ComposeEventDateQuery(DateTime fromDate、DateTime ToDate、IndexSearcher MySearcher)
{
BooleanQuery=新建BooleanQuery();
Query boolQuery3A=newtermquery(new Lucene.Net.Index.Term(“_language”,“en”));
Query eventDateQuery=new EventDateQuery1(boolQuery3A,MySearcher,fromDate,ToDate,false);
Add(eventDateQuery,BooleanClause.occurrent.MUST);
返回查询;
}
公共类EventDateQuery1:CustomScoreQuery
{
私人搜索者(Searcher);;
私有日期时间_fromDT;
私人日期时间;
私有只读字符串_dateFormat=“yyyyymmdd”;
private bool _shouldMatchNoneEvents=true;
public EventDateQuery1(查询子查询、搜索器搜索器、DateTime fromDT、bool shouldMatchNoEvents、int dateRange=14)
:base(子查询)
{
_搜索者=搜索者;
_fromDT=fromDT.日期;
_toDT=fromDT.AddDays(日期范围).Date;
_shoulldmatchnonevents=shoulldmatchnonevents;
}
public EventDateQuery1(查询子查询、搜索器搜索器、DateTime fromDT、DateTime toDT、bool shouldMatchNoEvents)
:base(子查询)
{
_搜索者=搜索者;
_fromDT=fromDT.日期;
_toDT=toDT.日期;
_shoulldmatchnonevents=shoulldmatchnonevents;
}
公共重写字符串ToString()
{
返回GenerateUniqueKey();
}
公共重写字符串到字符串(字符串字段)
{
返回GenerateUniqueKey();
}
公共重写字符串名称()
{
返回GenerateUniqueKey();
}
公共字符串GenerateUniqueKey()
{
返回String.Format(“EventDateQuery{0}{1}{2}”,_fromDT.ToString(_dateFormat),_toDT.ToString(_dateFormat),_shouldMatchNoEvents.ToString());
}
受保护的覆盖CustomScoreProvider GetCustomScoreProvider(IndexReader阅读器)
{
返回新的EventDateQueryCustomScoreProvider(读卡器,\u fromDT,\u toDT,\u shouldMatchNoEvents);
}
}
公共类EventDateQueryCustomScoreProvider:CustomScoreProvider
{
私有日期时间_fromDT;
私人日期时间;
私有只读字符串_dateFormat=“yyyyymmdd”;
private bool _shouldMatchNoneEvents=true;
私有浮动NoMatchFloat=0f;
专用浮点数匹配浮点数=1f;
公共事件DateQueryCustomsCoreProvider(IndexReader阅读器、DateTime fromDT、DateTime toDT、bool shouldMatchNoEvents)
:底座(读卡器)
{
_fromDT=fromDT.日期;
_toDT=toDT.日期;
_shoulldmatchnonevents=shoulldmatchnonevents;
}
公共覆盖浮点CustomScore(整数文档、浮点子查询核心、浮点VALRCCORE)
{
返回myScore(doc);
}
公共覆盖浮点CustomScore(整数文档、浮点子查询核心、浮点[]VALRCCORES)
{
返回myScore(doc);
}
公共浮动myScore(int doc)
{
//下面是一个假的实现,只是为了证明运行
如果(doc<10)
{
返回1F;
}
其他的
{
返回0F;
}
}
}
任何关于如何让Lucene不返回这些文档的建议都是非常好的。
提前感谢。

您可以编写一个自定义的
收集器
,只收集分数为
>0的文档。然后将此收集器的实例传递给
Search()
方法。有这样一个
收集器的实现

但是,如果您不需要所有结果,则建议您反对此解决方案。可能是这样的,因为您只选择了前1000个文档