4

我使用 lucene 版本 3.0.3.0,但我搜索的某些表达式无法正常工作。例如,如果我在字段“Model”上搜索“!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();
4

1 回答 1

8

!Fiesta OR Astra并不意味着你认为它意味着什么。这!Fiesta部分并不意味着“得到除嘉年华之外的所有东西”,正如你所料,而是更像是“禁止嘉年华”。Lucene 查询中的一个NOT术语只过滤掉结果,它没有找到任何东西。

您定义的唯一实际获取结果的查询是Astra. 因此,将找到包含 Astra 的所有内容,然后Fiesta将过滤掉所有包含 Astra 的内容。

为了执行我相信您期望的查询,您需要以下内容:

Astra OR (*:* !Fiesta)

*:*作为一个MatchAllDocsQuery. 由于您确实需要匹配所有文档来执行此类查询,因此预计它的性能会很差。


像这样对“布尔”逻辑的令人困惑的解释是我真的不喜欢 Lucene 的 AND/OR/NOT 语法的原因。+/- 更清晰、更强大,并且不会像这样引入奇怪的陷阱。

这篇关于该主题的优秀文章在一定程度上阐明了为什么您应该根据MUST/ MUST_NOT/SHOULD而非传统的布尔逻辑进行思考。

于 2013-07-31T16:12:03.403 回答