2013-07-31 23 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