Lucene. net: нет результатов поиска при использовании MultiFieldQueryParser - PullRequest
2 голосов
/ 21 апреля 2020

Я использую Lucene. Net версия 4.8.0 с. NET Core 3.1. В приведенном ниже примере кода я пишу новый индекс и добавляю в него три документа. Каждый документ содержит поля ProjectName, Customer и Country.

. Когда я анализирую запрос "Germany", поиск возвращает 2 совпадения для документов, содержащих слово «Германия» в любом из его поля. Однако, когда я анализирую запрос "Country:Germany", поиск возвращает 0 совпадений, хотя в его поле Country явно есть документ со значением «Германия».

Что я делаю неправильно?

Я также проверил свой индекс с помощью инструмента Люка (https://github.com/DmitryKey/luke/releases/tag/4.8.0). С Люком, поиск работает нормально для той же директории индекса.

Мой C# код здесь:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Lucene.Net.Analysis.Standard;
using Lucene.Net.Documents;
using Lucene.Net.Index;
using Lucene.Net.QueryParsers.Classic;
using Lucene.Net.Search;
using Lucene.Net.Store;
using Lucene.Net.Util;
using Directory = System.IO.Directory;

namespace LuceneTestApp
{
    class Program
    {
        static string CreateTestIndex()
        {
            string indexDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
            if(Directory.Exists(indexDir))
                throw new IOException("Random index directory already exists. Please try again.");

            using var dir = FSDirectory.Open(indexDir);
            using var analyzer = new StandardAnalyzer(LuceneVersion.LUCENE_48);
            var indexConfig = new IndexWriterConfig(LuceneVersion.LUCENE_48, analyzer);
            using var writer = new IndexWriter(dir, indexConfig);

            AddDocumentTo(writer, "AwesomeProject_1", "Volkswagen", "Germany");
            AddDocumentTo(writer, "AwesomeProject_2", "Ford", "USA");
            AddDocumentTo(writer, "AwesomeProject_3", "Audi Germany", "France");

            writer.Commit();
            return indexDir;
        }

        static void AddDocumentTo(IndexWriter writer, string projectName, string customer, string country)
        {
            var doc = new Document();
            doc.Add(new StringField( "ProjectName", projectName, Field.Store.YES));
            doc.Add(new TextField(   "Customer",    customer,    Field.Store.YES));
            doc.Add(new TextField(   "Country",     country,     Field.Store.YES));
            writer.AddDocument(doc);
        }

        static IList<string> Search(string indexDir, string queryString)
        {
            using var dir = FSDirectory.Open(indexDir);
            using var reader = DirectoryReader.Open(dir);
            using var analyzer = new StandardAnalyzer(LuceneVersion.LUCENE_48);
            var searcher = new IndexSearcher(reader);

            string[] searchFields = {"ProjectName", "Customer", "Country"};
            var queryParser = new MultiFieldQueryParser(LuceneVersion.LUCENE_48, searchFields, analyzer);
            queryParser.DefaultOperator = Operator.AND;
            var query = queryParser.Parse(queryString.ToLowerInvariant());

            int maxNumHits = 10;
            var topDocs = searcher.Search(query, maxNumHits);

            return topDocs.ScoreDocs.Select(hit => $"Score {hit.Score,5:0.000} DocId {hit.Doc}").ToList();
        }

        static void Main(string[] args)
        {
            Console.WriteLine("=================");

            string indexDir = CreateTestIndex();
            IList<string> hitsOne = Search(indexDir, "Germany");
            IList<string> hitsTwo = Search(indexDir, "Country:Germany");

            Console.WriteLine($"Search one yields {hitsOne.Count} hits.");
            Console.WriteLine($"Search two yields {hitsTwo.Count} hits.");

            Console.WriteLine("=================\n\n");
        }
    }
}

1 Ответ

1 голос
/ 22 апреля 2020

Я нашел ошибку, которую сделал. Очевидно, что имена полей в Lucene чувствительны к регистру. Следовательно, в моем случае код queryString.ToLowerInvariant() превратил строку запроса "Country:Germany" в "country:Germany" и, таким образом, ничего не было найдено, поскольку строчное поле country не существует.

Решение: Удалить звонок на ToLowerInvariant().

...