2011-05-25 83 views
1

我試圖將我的搜索功能轉換爲允許涉及多個單詞的模糊搜索。我現有的搜索代碼如下所示:爲什麼此Lucene.Net查詢失敗?

 // Split the search into seperate queries per word, and combine them into one major query 
     var finalQuery = new BooleanQuery(); 

     string[] terms = searchString.Split(new[] { " " }, StringSplitOptions.RemoveEmptyEntries); 
     foreach (string term in terms) 
     { 
      // Setup the fields to search 
      string[] searchfields = new string[] 
      { 
       // Various strings denoting the document fields available 
      }; 

      var parser = new MultiFieldQueryParser(Lucene.Net.Util.Version.LUCENE_29, searchfields, new StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_29)); 
      finalQuery.Add(parser.Parse(term), BooleanClause.Occur.MUST); 
     } 

     // Perform the search 
     var directory = FSDirectory.Open(new DirectoryInfo(LuceneIndexBaseDirectory)); 
     var searcher = new IndexSearcher(directory, true); 
     var hits = searcher.Search(finalQuery, MAX_RESULTS); 

這正常工作,如果我有一個的「我的名字叫安德魯」的名稱字段的實體,我執行了「安德魯名稱」進行搜索,Lucene的正確認定正確的文件。現在我想啓用模糊搜索,以便正確找到「Anderw Name」。我改變了我的方法,使用下面的代碼:

 const int MAX_RESULTS = 10000; 
     const float MIN_SIMILARITY = 0.5f; 
     const int PREFIX_LENGTH = 3; 

     if (string.IsNullOrWhiteSpace(searchString)) 
      throw new ArgumentException("Provided search string is empty"); 

     // Split the search into seperate queries per word, and combine them into one major query 
     var finalQuery = new BooleanQuery(); 

     string[] terms = searchString.Split(new[] { " " }, StringSplitOptions.RemoveEmptyEntries); 
     foreach (string term in terms) 
     { 
      // Setup the fields to search 
      string[] searchfields = new string[] 
      { 
       // Strings denoting document field names here 
      }; 

      // Create a subquery where the term must match at least one of the fields 
      var subquery = new BooleanQuery(); 
      foreach (string field in searchfields) 
      { 
       var queryTerm = new Term(field, term); 
       var fuzzyQuery = new FuzzyQuery(queryTerm, MIN_SIMILARITY, PREFIX_LENGTH); 
       subquery.Add(fuzzyQuery, BooleanClause.Occur.SHOULD); 
      } 

      // Add the subquery to the final query, but make at least one subquery match must be found 
      finalQuery.Add(subquery, BooleanClause.Occur.MUST); 
     } 

     // Perform the search 
     var directory = FSDirectory.Open(new DirectoryInfo(LuceneIndexBaseDirectory)); 
     var searcher = new IndexSearcher(directory, true); 
     var hits = searcher.Search(finalQuery, MAX_RESULTS); 

不幸的是,有了這個代碼,如果我提交了搜索查詢「安德魯名稱」(同前),我得到任何結果回來。

其核心思想是所有術語必須在至少一個文檔字段中找到,但每個術語可以駐留在不同的字段中。有沒有人有任何想法,爲什麼我的重寫查詢失敗?


最後編輯:好的事實證明我是在通過大量的複雜化這一點,也沒有必要從我的第一種方法改變。回覆到第一代碼片段後,我啓用的模糊搜索,通過改變

finalQuery.Add(parser.Parse(term), BooleanClause.Occur.MUST); 

finalQuery.Add(parser.Parse(term.Replace("~", "") + "~"), BooleanClause.Occur.MUST); 
+0

MIN_SIMILARITY和PREFIX_LENGTH的值是什麼? finalQuery.ToString()的價值是什麼? – sisve 2011-05-26 03:35:20

+0

我在我的文章中添加了常用的常量。 – KallDrexx 2011-05-26 03:39:16

+0

索引時使用什麼分析器? – sisve 2011-05-26 03:48:06

回答

3

如果我將searchString重寫爲小寫,您的代碼適用於我。我假設你在索引時使用StandardAnalyzer,並且它會生成小寫字母。您需要1)通過同一個分析器傳遞您的標記(以啓用相同的處理),2)應用與分析器相同的邏輯或3)使用與您所做處理相匹配的分析器(WhitespaceAnalyzer)。

+0

我正在使用'StandardAnalyzer'進行索引,但現在我查看了我的代碼第二代碼塊,我沒有使用任何分析器。但是,我並沒有立即看到如何在我的第二代碼塊中使用分析儀。我知道如何在第一個示例中使用它,因爲我正在使用查詢解析器,但我沒有在第二個代碼塊中使用它 – KallDrexx 2011-05-26 04:05:37

+0

使用QueryParser,以便使用分析器並獲得對其他查詢(如短語)的支持。只需遍歷生成的查詢,並用FuzzyQuery替換TermQuery即可。您可以在http://devhost.se/blog/post/2011/04/21/A-QueryVisitor-for-Lucene上使用QueryVisitor。aspx – sisve 2011-05-26 04:28:46

+0

我其實剛剛意識到我根本不需要使用第二種方法,而我只需要使用第一種方法,但在搜索項中添加〜(請參閱我的編輯) – KallDrexx 2011-05-26 04:33:34

1

希望此行:

var queryTerm = new Term(term); 

看起來像這樣:

var queryTerm = new Term(field, term); 

現在你是海對於空字符串(它永遠不會被找到)的字段term(可能不存在)。

+0

不幸的是,這並沒有完全解決我的問題。當姓名字段爲「我的名字是安德魯」時,前面提到的有關'安德魯名字'的搜索不會返回任何結果。 – KallDrexx 2011-05-25 21:43:56