2013-07-31 4 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 부분은 "피에스타를 제외한 모든 것을 얻으십시오"라는 뜻이 아니라 "피에스타 금지"와 같은 의미입니다. Lucene 쿼리의 NOT 용어는 결과를 필터링 만하고 아무것도 찾지 않습니다.

실제로 결과를 가져 오는 쿼리는 Astra입니다. 그래서 Astra를 포함한 모든 것이 발견 될 것이고 Fiesta을 가진 것은 걸러 낼 것입니다. MatchAllDocsQuery

Astra OR (*:* !Fiesta) 

*:* : 나는 당신이 기대하고 믿는 쿼리를 수행하기 위해

, 당신은 뭔가를해야합니다. 이러한 종류의 쿼리를 수행하기 위해 모든 문서를 일치시켜야하므로 성능이 좋지 않을 것으로 예상됩니다.


"부울"논리를 혼란스럽게 해석하는 이유는 내가 Lucene의 AND/OR/NOT 구문을 좋아하지 않는 이유입니다. +/-는 훨씬 더 명확하고 강력하며, 이런 괴상한 점을 소개하지 않습니다. 오히려 기존의 부울 논리보다, MUST/MUST_NOT/SHOULD의 관점에서 생각해야하는 이유

This excellent article on the topic 다소 명확하게.

+0

내게 두통을 저장했습니다. – goten

관련 문제