c# - 为什么 MultiFieldQueryParser 比手动创建查询慢得多?

标签 c# lucene.net

我正在使用 Lucene.net 为产品目录编制索引。我正在使用 ANTS Profiler 分析我的搜索,我注意到使用 MultiFieldQueryParser 创建和解析查询的行为几乎与实际搜索一样长(大约 100 毫秒)。然后我尝试手动创建查询,这发生得非常快(大约 1 毫秒)。我宁愿不必手动解析,尽管它确实给了我相同的结果集,但我担心我可能不会处理某些用例或输入(尽管输入来自网站上的文本搜索,用户不会知道关于 Lucene 的搜索语法的任何信息)。我的代码(两种方法)如下:

        IApplicationSettings settings = new ApplicationSettingService();
        FSDirectory directory = FSDirectory.Open(new DirectoryInfo(settings.GetSetting<string>("LuceneMainSearchDirectory")));
        RAMDirectory ramDir = new RAMDirectory(directory);
        _Searcher = new IndexSearcher(ramDir, true);        
        string[] searchFields = new string[] { "ProductName", "ProductLongDescription", "BrandName", "CategoryName" };

        //Add a wildcard character to end of search to give broader results 
        if (!searchTerm.EndsWith(" ")) { searchTerm = searchTerm + "*"; }


        //Use query parser...this  block typically takes about 100ms on my machine, roughly 40% on the constructor and 60% on the call to Parse
        MultiFieldQueryParser multiParser = new MultiFieldQueryParser(Lucene.Net.Util.Version.LUCENE_29, searchFields, _analyzer);
        multiParser.SetDefaultOperator(QueryParser.AND_OPERATOR);
        Query query = multiParser.Parse(searchTerm);



        //Manually create query....this block doesn't even take 1ms on my machine
        BooleanQuery booleanQuery = new BooleanQuery(true);
        var terms = searchTerm.Split(' ');
        foreach (string s in terms)
        {
            BooleanQuery subQuery = new BooleanQuery(true);
            if (!s.EndsWith("*"))
            {
                Query query1 = new TermQuery(new Term("ProductName", s));
                Query query2 = new TermQuery(new Term("ProductLongDescription", s));
                Query query3 = new TermQuery(new Term("BrandName", s));
                Query query4 = new TermQuery(new Term("CategoryName", s));
                subQuery.Add(query1, BooleanClause.Occur.SHOULD);
                subQuery.Add(query2, BooleanClause.Occur.SHOULD);
                subQuery.Add(query3, BooleanClause.Occur.SHOULD);
                subQuery.Add(query4, BooleanClause.Occur.SHOULD);
            }
            else
            {
                Query query1 = new WildcardQuery(new Term("ProductName", s));
                Query query2 = new WildcardQuery(new Term("ProductLongDescription", s));
                Query query3 = new WildcardQuery(new Term("BrandName", s));
                Query query4 = new WildcardQuery(new Term("CategoryName", s));
                subQuery.Add(query1, BooleanClause.Occur.SHOULD);
                subQuery.Add(query2, BooleanClause.Occur.SHOULD);
                subQuery.Add(query3, BooleanClause.Occur.SHOULD);
                subQuery.Add(query4, BooleanClause.Occur.SHOULD);
            }
            booleanQuery.Add(subQuery, BooleanClause.Occur.MUST);
        }


    //Run the search....results are the same for simple multiword text queries
        var result2 = _Searcher.Search(booleanQuery, null, maxResults);
        var result = _Searcher.Search(query, null, maxResults);

使用手动查询构建来拯救我的一个选择可能是共享 MultiFieldQueryParser,但我收集到它的 Parse 方法不是线程安全的(尽管我只阅读了与 Java 版本相关的内容......如果我是,请纠正我这个假设是错误的)。

我是做错了什么还是这只是野兽的本性?

最佳答案

MultiFieldQueryParser 只是在场景下使用多个常规 QueryParser,它会为您要查询的每个字段创建一个。

QueryParser 的创建比手动创建 Query 的成本更高是正常的。

它处理此处记录的复杂查询语法:Apache Lucene - Query Parser Syntax

它还将使用您指定的 Analyzer 处理搜索查询。如果您在索引时使用 Analyzer,则必须在搜索代码中使用相同的 Analyzer/逻辑。如果不这样做,您最终会丢失结果。

如果您使用空白分析器进行索引,那么您手动构建 BooleanQuery 的代码就可以了。

关于c# - 为什么 MultiFieldQueryParser 比手动创建查询慢得多?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8512559/

相关文章:

c# - 共享通用代码以了解引用类型的原因和效率影响

c# - 通信对象 System.ServiceModel.Channels.ServiceChannel 不能用于通信,因为它处于 Faulted 状态

c# - 如何在wpf中获取选中的单选按钮的值

Lucene 搜索和下划线

c# - 服务类可以以及如何继承普通类?

C# 和 Java 方法的区别

lucene - 我可以在 Lucene.Net 中通过多个线程同时使用同一个 IndexSearcher 实例吗?

search - 使用 Lucene.net 进行精确短语搜索

c# - 为什么这个 Lucene.Net 查询会失败?

date - 使用 Lucene.Net 在两个日期之间搜索