Ima*_*989 3 lucene not-operator operator-keyword
我使用lucene版本3.0.3.0,但我搜索的一些表达式无法正常工作.例如,如果我在"模型"字段上搜索"!Fiesta OR Astra",则仅返回"vauxhallAstra"并且不返回"fordFocus".我的代码如下:
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();
Run Code Online (Sandbox Code Playgroud)
!Fiesta OR Astra并不意味着你认为它意味着什么.这!Fiesta部分并不意味着,"除了嘉年华之外的所有东西",正如你所料,但更像是"禁止嘉年华".一个NOT在Lucene的查询条件,仅筛选出的结果,它没有发现任何东西.
您定义的唯一实际获取结果的查询是Astra.所以包含Astra的所有东西都会被找到,然后任何东西Fiesta都会被过滤掉.
为了执行我认为你期待的查询,你需要这样的东西:
Astra OR (*:* !Fiesta)
Run Code Online (Sandbox Code Playgroud)
*:*作为一个MatchAllDocsQuery.由于您确实需要匹配所有文档来执行此类查询,因此可能会表现不佳.
像这样令人困惑的"布尔"逻辑解释是我真的不喜欢Lucene的AND/OR/NOT语法的原因.+/-更清晰,更强大,并没有引入像这样的古怪的陷阱.
这篇关于该主题的优秀文章澄清了为什么你应该考虑MUST/ MUST_NOT/ SHOULD而不是传统的布尔逻辑.