简体   繁体   English

Elasticsearch.NET 中的复合查询

[英]Compound query in Elasticsearch.NET

Imagine I have an index with a bunch of Order objects in it想象一下,我有一个包含一堆Order对象的索引

class Order
{
    int CustomerId { get; set; }
    DateTime OrderDate { get; set; }
    // Other fields
}

For a particular customer ID, I am able to find out the last order that the customer made with the following query:对于特定的客户 ID,我可以通过以下查询找到客户的最后一个订单:

IElasticClient client;

async Task<Order> GetLastOrder(int customerId)
{
    var searchResponse = await client.SearchAsync<Order>(s => s
        .Query(q => q
            .Term(f => f
                .Field(e => e.CustomerId)
                .Term(customerId)) && q
            .DateRange(r => r
                .Field(e => e.OrderDate)
                .LessThan(DateMath.Now)))
        .Sort(o => o
            .Descending(e => e.OrderDate))
        .Size(1));

    return searchResponse.ApiCall.Success
        ? searchResponse.Documents.First()
        : null;
}

However, in order to support the data loader pattern, I want to query the last order made by multiple customers, given by a collection of customer IDs.但是,为了支持数据加载器模式,我想查询多个客户的最后一个订单,由一组客户 ID 给出。 I started off like this:我是这样开始的:

async Task<IDictionary<int, Order>> GetLastOrders(IEnumerable<int> customerIds)
{
    var searchResponse = await client.SearchAsync<Order>(s => s
        .Query(q => q
            .Terms(f => f
                .Field(e => e.CustomerId)
                .Terms(customerIds)) && q
            .DateRange(r => r
                .Field(e => e.OrderDate)
                .LessThan(DateMath.Now)))
        .Sort(o => o
            .Descending(e => e.OrderDate))
        .Size(1));

    return searchResponse.ApiCall.Success
        ? searchResponse.Documents.ToDictionary(i => i.CustomerId)
        : new Dictionary<string, Order>();
}

Unfortunately this does not work, as it only returns the first record of entire query, which will only return a single Order .不幸的是,这不起作用,因为它只返回整个查询的第一条记录,它只会返回一个Order How can I modify this query to return one Order per customer ID?如何修改此查询以针对每个客户 ID 返回一个Order

Collapse can be used to return top most record for a field 折叠可用于返回字段的最高记录

await _client.SearchAsync<Order>(s => s
                                        .Query(q => q
                                        .Terms(f => f
                                        .Field(e => e.CustomerId)
                                        .Terms(cuIds)) && q
                                        .DateRange(r => r
                                                         .Field(e => e.OrderDate)
                                                         .LessThan(DateMath.Now)))
                                        .Sort(o => o
                                              .Descending(e => e.OrderDate))
                                        .Collapse(c => c.Field(e => e.CustomerId))
                                        .Size(10)
                                        );

corresponding query in DSL DSL 中的相应查询

{
  "collapse": {
    "field": "customerId"
  },
  "query": {
    "bool": {
      "must": [
        {
          "terms": {
            "customerId": [
              1,
              2
            ]
          }
        },
        {
          "range": {
            "orderDate": {
              "lt": "now"
            }
          }
        }
      ]
    }
  },
  "size": 10,
  "sort": [
    {
      "orderDate": {
        "order": "desc"
      }
    }
  ]
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM