2011-12-14 9 views
3

Lucene.netを使用して商品カタログのインデックスを作成しています。私はANTS Profilerを使用して検索をプロファイリングしていましたが、MultiFieldQueryParserを使用してクエリを作成および解析する行為は、実際の検索(約100ms)とほぼ同じくらい長くかかることに気付きました。私はその後、手動でクエリを作成しようとしましたが、これは非常に高速です(約1ms)。手動で解析する必要はありませんが、結果セットは同じですが、特定のユースケースや入力を処理していない可能性があります(ただし、入力はウェブサイトのテキスト検索から来ていますが、ユーザーはわかりませんLuceneの検索構文に関するもの)。以下のように(両方の方法で)私のコードは次のとおりです。MultiFieldQueryParserは手作業でクエリを作成するよりもずっと遅いのはなぜですか?

 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バージョンとの関係で...私がその仮定で間違っている場合は私を修正してください)。

私は何か間違っているのですか?これは獣の本質ですか?

答えて

5

MultiFieldQueryParserは、シーン内で複数の通常のQueryParserを使用するだけで、照会するフィールドごとに1つずつ作成されます。

QueryParserの作成は、手作業でQueryを作成するよりもコストが高くなるのが普通です。

それはここに文書化され、複雑なクエリsynthaxハンドル:それはまた、あなたが指定したAnalyzerを使用して、検索クエリを処理するApache Lucene - Query Parser Syntax

を。インデックス時にAnalyzerを使用する場合は、検索コードで同じAnalyzer /ロジックを使用する必要があります。あなたがしなければ、結果が失われることになります。

ホワイトスペースアナライザーを使用してインデックスを作成した場合、BooleanQueryを手動で作成するコードは問題ありません。

関連する問題