2013-07-31 53 views
3

我使用的是lucene 3.0.3.0版,但我搜索的某些表達式無法正常工作。例如,如果我在字段「Model」中搜索「!Fiesta OR Astra」,則僅返回「vauxhallAstra」,而不返回「fordFocus」。我的代碼如下:NOT運算符在查詢lucene中不起作用

var fordFiesta = new Document(); 

     fordFiesta.Add(new Field("Id", "1", Field.Store.YES, Field.Index.NOT_ANALYZED)); 

     fordFiesta.Add(new Field("Make", "Ford", Field.Store.YES, Field.Index.ANALYZED)); 

     fordFiesta.Add(new Field("Model", "Fiesta", Field.Store.YES, Field.Index.ANALYZED)); 



     var fordFocus = new Document(); 

     fordFocus.Add(new Field("Id", "2", Field.Store.YES, Field.Index.NOT_ANALYZED)); 

     fordFocus.Add(new Field("Make", "Ford", Field.Store.YES, Field.Index.ANALYZED)); 

     fordFocus.Add(new Field("Model", "Focus", Field.Store.YES, Field.Index.ANALYZED)); 



     var vauxhallAstra = new Document(); 

     vauxhallAstra.Add(new Field("Id", "3", Field.Store.YES, Field.Index.NOT_ANALYZED)); 

     vauxhallAstra.Add(new Field("Make", "Vauxhall", Field.Store.YES, Field.Index.ANALYZED)); 

     vauxhallAstra.Add(new Field("Model", "Astra", Field.Store.YES, Field.Index.ANALYZED)); 







     Directory directory = FSDirectory.Open(new DirectoryInfo(Environment.CurrentDirectory + "\\LuceneIndex")); 

     Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_30); 





     var writer = new IndexWriter(directory, analyzer, true, IndexWriter.MaxFieldLength.LIMITED); 

     writer.AddDocument(fordFiesta); 

     writer.AddDocument(fordFocus); 

     writer.AddDocument(vauxhallAstra); 


     writer.Optimize();      

     writer.Close(); 

     IndexReader indexReader = IndexReader.Open(directory, true); 
     Searcher indexSearch = new IndexSearcher(indexReader); 

     var queryParser = new QueryParser(Version.LUCENE_30, "Model", analyzer); 
     var query = queryParser.Parse("!Fiesta OR Astra"); 

     Console.WriteLine("Searching for: " + query.ToString()); 
     TopDocs resultDocs = indexSearch.Search(query, 200);    
     Console.WriteLine("Results Found: " + resultDocs.MaxScore); 

     var hits = resultDocs.ScoreDocs; 
     foreach (var hit in hits) 
     { 
      var documentFromSearcher = indexSearch.Doc(hit.Doc); 
      Console.WriteLine(documentFromSearcher.Get("Make") + " " + documentFromSearcher.Get("Model")); 
     } 

     indexSearch.Close(); 
     directory.Close(); 

     Console.ReadKey(); 

回答

8

!Fiesta OR Astra並不意味着你的想法。正如你所期望的那樣,!Fiesta部分並不意味着「得到除嘉年華之外的所有東西」,而更像是「禁止嘉年華」。 A NOT Lucene查詢中的術語只會過濾掉結果,它找不到任何內容。

您定義的唯一查詢將實際獲取結果爲Astra。所以包含Astra的所有東西都會被找到,那麼Fiesta的任何東西都會被過濾掉。

爲了執行查詢,我相信你期待,你需要這樣的:

Astra OR (*:* !Fiesta) 

*:*MatchAllDocsQuery。由於您確實需要匹配所有文檔才能執行此類查詢,因此預計執行效果不佳。


混淆像這樣的「布爾」邏輯解釋是爲什麼我真的不喜歡AND/OR/NOT語法的Lucene。 +/-更清晰,更強大,並且不會引入像這樣的古怪問題。

This excellent article on the topic澄清了爲什麼你應該考慮根據MUST/MUST_NOT/SHOULD,而不是傳統的布爾邏輯。

+0

你救了我頭痛 – goten