Использование NEST для elasticsearch. Как я могу искать родителей на основе дочерних атрибутов

#c# #elasticsearch #nest

#c# #elasticsearch #nest

Вопрос:

Я пытаюсь выполнить простой поиск, используя NEST для клиентов с учетом конкретных местоположений клиентов. POCOS являются:

 class Customer
{
    public int CustomerId { get; set; }
    public string CustomerName { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Identifiers { get; set; }
    public string isIndividual { get; set; }
    public double Balance { get; set; }
    public List<CustomerLocation> Locations { get; set; }

class CustomerLocation
{
    public int CustomerLocationId { get; set; }
    public string StreetLine1 { get; set; }
    public string Streetline2 { get; set; }
    public string City { get; set; }
   
}
  

В настоящее время я использую эту процедуру поиска, но она завершается неудачей:

                         var searchResponse = _client.Search<Customer>(s => s
                   .Query(q => q
                        .HasChild<CustomerLocation >(hp => hp
                            .Query(qq => qq
                                .Match(m => m
                                    .Field(f => f.City )
                                    .Query(queryText)
                                )
                                
                            )
                         )
                     )
                   .Size(500)
                    );
  

Предоставленное сообщение об ошибке является:

Система.Результат исключения = 0x80131500 Сообщение = Неверный поиск. Ошибка: Неверный ответ NEST, созданный на основе неудачного (400) вызова низкого уровня в POST: /customers /_search?typed_keys= true

Журнал аудита этого вызова API:

  • [1] SniffOnStartup: Принял: 00:00:00.2448689
  • [2] SniffSuccess: Узел: http://localhost:9200 / Взял: 00:00:00.2288784
  • [3] PingSuccess: узел:http://127.0.0.1:9200 / Взял: 00:00:00.0029899
  • [4] Плохой ответ: узел: http://127.0.0.1:9200 / Взял: 00:00:00.1639172

Исключение OriginalException: Elasticsearch.Net.Исключение ElasticsearchClientException: удаленный сервер вернул ошибку: (400) Неверный запрос.. Вызов: Код состояния 400 из: POST / customers /_search?typed_keys= true. Ошибка сервера: Тип: исключение search_fase_execution_exception Причина: «сбой всех сегментов» —> System.Net.WebException: Удаленный сервер вернул ошибку: (400) Неверный запрос.

в System.Net.HttpWebRequest.GetResponse() в Elasticsearch.Net.HttpWebRequestConnection.Запрос [TResponse] (requestData requestData) в C:Usersrusscsourceelasticsearch-netsrcElasticsearch.Net Connection HttpWebRequestConnection.cs: строка 63

Любые идеи — высоко ценятся.

Ответ №1:

Связь между клиентами и местоположениями не является родительско-дочерней в терминах Elasticsearch, что требуется для использования has_child запроса.

Если Locations свойство в Customer не отображено явно, оно будет object отображением типа, что позволит вам выполнять

 var queryText = "Sydney";

var searchResponse = client.Search<Customer>(s => s
    .Query(q => q
       .Match(m => m
           .Field(f => f.Locations.First().City)
           .Query(queryText)
       )
    )
    .Size(500)
);
  

Примечание: f => f.Locations.First().City это просто выражение для построения пути к полю JSON строго типизированным способом путем навигации по объектному графу. Это не означает «город первого местоположения», но оценивается как «город любого местоположения».

Это генерирует следующий запрос

 {
  "query": {
    "match": {
      "locations.city": {
        "query": "Sydney"
      }
    }
  },
  "size": 500
}
  

Однако при данной структуре POCO вполне вероятно, что вы захотите выполнить поиск по нескольким свойствам местоположения. В этом случае Locations должно быть явно отображено как nested тип данных.

При отображении в виде вложенного типа данных запрос будет

 var queryText = "Sydney";

var searchResponse = client.Search<Customer>(s => s
    .Query(q => q
        .Nested(n => n
            .Path(p => p.Locations)
            .Query(nq => nq
                .Match(m => m
                    .Field(f => f.Locations.First().City)
                    .Query(queryText)
                )
            )
        )
    )
    .Size(500)
);