Как реализовать Elasticsearch Suggester’а?

#c# #asp.net-core #elasticsearch #nest

#c# #asp.net-core #elasticsearch #гнездо

Вопрос:

Я пытаюсь реализовать пример кода, который использует функцию предложения из Elastic Search.

Индексированный документ состоит из плоского POCO

 public class CandidateDocument
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public string FirstName { get; set; }
    public DateTime BirthDate { get; set; }
    public CompletionField Suggest { get; set; }
}
  

Отображение выглядит следующим образом

 var client = new ElasticClient(settings);

client.Indices.Create("candidates", c =>
                                           c.Map<CandidateDocument>(m =>
                                                            m.Properties(ps => ps.Text(s => s.Name(n => n.Name)
                                                                                             .Store(false)
                                                                                             .Fields(f => f.Keyword(k => k.Name("nameRaw"))))
                                                                                 .Text(s => s.Name(n => n.FirstName)
                                                                                             .Store(false)
                                                                                             .Fields(f => f.Keyword(k => k.Name("firstNameRaw"))
                                                                                 
                                                                                 .Date(s => s.Name(n => n.BirthDate).Format("ddMMyyyy"))
                                                                                 .Keyword(s => s.Name(n => n.Id))))
                                                                               
                                                                                 .Completion(c => c.Name(n => n.Suggest)))));
  

Индексирование документа выглядит следующим образом:

  var candidateDocument = new CandidateDocument
        {
            Id = Guid.NewGuid(),
            Name = "Lennon",
            FirstName = "John",
            BirthDate = DateTime.Now,
            Suggest = new CompletionField
            {
                Input = new[] { "Lennon" },
            }
        };

    var indexResponse = await this.elasticClient.IndexAsync(candidateDocument, i => i.Index("candidates"));
  

И мой запрос :

 var searchResponse = await this.elasticClient.SearchAsync<CandidateDocument>(s => s.Index("candidates").Suggest(su => su
                                                                                                       .Completion("suggestions", c => c
                                                                                                                                        .Field(f => f.Suggest)
                                                                                                                                        .Prefix(query)
                                                                                                                                        .Fuzzy(f => f.Fuzziness(Fuzziness.Auto))
                                                                                                                                        .Size(5))));
  

Я столкнулся с проблемой, связанной со следующей проблемой :

Исключение Elasticsearch.Net.ElasticsearchClientException: запрос не удалось выполнить. Вызов: Код статуса 400 из: POST /candidates/_search?typed_keys=true. Ошибка сервера: Тип: search_fase_execution_exception Причина: «сбой всех сегментов» Вызвано by: «Тип: illegal_argument_exception Причина: «не найдено сопоставление для поля [предложить]» Вызвано by: «Тип: illegal_argument_exception Причина: «не найдено сопоставление для поля [предложить]»

Глядя на мое отображение индекса с использованием kibana :

       "suggest": {
      "properties": {
        "input": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        }
      }
    }
  

Кстати, я использую последнюю версию Nest (7.9.0) в .NET Core 3.1

Я был бы признателен за вашу помощь.

Ответ №1:

Была такая же проблема, решаемая явными сопоставлениями :

 _elasticClient.Indices.Create("candidates", c => c
 .Map<CandidateDocument>(m => m
     .Properties(ps => ps
         .Completion(s => s
             .Name(n => n.Suggest)))));

public class CandidateDocument
{        
    public Guid? Id { get; set; }
    public CompletionField Suggest { get; set; }
}
  

Ответ №2:

Похоже, что индекс кандидатов и поле предложения, возможно, уже существовали на момент выдачи запроса на создание индекса с сопоставлением. Вы могли бы проверить CreateIndexResponse возвращенное значение, чтобы убедиться, что это так; IsValid свойство будет false, а в ответе будут указаны сведения об ошибке, объясняющие, почему.

Поведение Elasticsearch по умолчанию создаст индекс и сопоставление, если поступит запрос на индексацию документа в нем, выводя сопоставление для полей на основе первого документа, который он видит. Это полезное поведение для многих вариантов использования, но для вариантов использования поиска обычно требуется контролировать создание индексов с явными сопоставлениями, как вы это делаете, поэтому, чтобы отключить это поведение, вы можете установить для action.auto_create_index параметра кластера значение false .. Теперь, если вы удалите индекс и воссоздадите его снова с помощью вашего запроса на создание индекса, он не будет автоматически создан до того, как у вас появится возможность явно создать его.

Ответ №3:

Вы правы, определение сопоставления было создано при индексировании документа, не созданного на основе описанного мной определения сопоставления. Проверка свойства CreateIndexResponse isValid указывает, как вы и ожидали, на проблему.

Мне потребовалось время, чтобы разобраться с основной проблемой: я использовал образ ES Docker версии 6.3.0 и клиент Nest 7. * Совместимость моего ES с моим клиентом Nest устранила проблему.

Спасибо за вашу помощь.