首页 > 解决方案 > 使用 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)
                    );

提供的错误消息是:

System.Exception HResult=0x80131500 消息=无效搜索。错误是:从 POST 上的不成功 (400) 低级别调用构建的无效 NEST 响应:/customers/_search?typed_keys=true

此 API 调用的审计跟踪:

OriginalException:Elasticsearch.Net.ElasticsearchClientException:远程服务器返回错误:(400)错误请求..调用:状态代码 400 来自:POST /customers/_search?typed_keys=true。ServerError:类型:search_phase_execution_exception 原因:“所有分片失败”---> System.Net.WebException:远程服务器返回错误:(400)错误请求。

在 System.Net.HttpWebRequest.GetResponse() 在 Elasticsearch.Net.HttpWebRequestConnection.Request[TResponse](RequestData requestData) 在 C:\Users\russc\source\elasticsearch-net\src\Elasticsearch.Net\Connection\HttpWebRequestConnection.cs :第 63 行

任何想法 - 非常感谢。

标签: c#elasticsearchnest

解决方案


客户和位置之间的关系不是 Elasticsearch 术语中的父/子关系,这是使用查询所必需has_child

除非显式映射,否则Locations属性 onCustomer将是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)
);

推荐阅读