按聚合结果筛选Elasticsearch 5

时间:2017-02-02 18:45:37

标签: c# elasticsearch nest

我正在使用ES 5.在C#上使用Nest lib。

我的模型中有两个实体,联系人和事件。我有一个要求,我必须得到所有联系,而不是超过N个事件(非常类似于对SQL的查询)。联系人是事件父母,因此我可以使用父/子策略进行过滤。

我能够获得联系人的聚合,因为我无法通过这些聚合来过滤联系人。

我做了类似的事情:

var queryResult = client.Search<Contact>(s => s
            .Index("contact*")                
            .Query(q => q
                ...
            )
            .Aggregations(a => a
                .Children<Event>("filter_event", ca => ca.Aggregations(ca2 => ca2
                    .Filter("filter1", f => f.Filter(fq => fq.Term(t => t.Field(tf => tf.EventName).Value("Event1")))
                        .Aggregations(fa => fa
                            .Terms("filter1Contacts", v => v.Field(faf => faf.EventContactGuid).Size(int.MaxValue).MinimumDocumentCount(5))
                        )
                    )                        
            )))
        );

使用此代码,我只能获得超过5个事件的联系人的聚合,但我没有找到根据这些聚合结果过滤联系人的方法。

在ES 5中有一种方法可以做到这一点吗?

1 个答案:

答案 0 :(得分:1)

您可以使用has_child query,这是尝试Linqpad

的示例
void Main()
{
    var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));
    var defaultIndex = "orders";
    var connectionSettings = new ConnectionSettings(pool)
            .DefaultIndex(defaultIndex)
            .InferMappingFor<Order>(m => m
                .IdProperty(f => f.Customer)
            )
            .PrettyJson()
            .DisableDirectStreaming()
            .OnRequestCompleted(response =>
                {
                    // log out the request
                    if (response.RequestBodyInBytes != null)
                    {
                        Console.WriteLine(
                            $"{response.HttpMethod} {response.Uri} \n" +
                            $"{Encoding.UTF8.GetString(response.RequestBodyInBytes)}");
                    }
                    else
                    {
                        Console.WriteLine($"{response.HttpMethod} {response.Uri}");
                    }

                    Console.WriteLine();

                    // log out the response
                    if (response.ResponseBodyInBytes != null)
                    {
                        Console.WriteLine($"Status: {response.HttpStatusCode}\n" +
                                 $"{Encoding.UTF8.GetString(response.ResponseBodyInBytes)}\n" +
                                 $"{new string('-', 30)}\n");
                    }
                    else
                    {
                        Console.WriteLine($"Status: {response.HttpStatusCode}\n" +
                                 $"{new string('-', 30)}\n");
                    }
                });

    var client = new ElasticClient(connectionSettings);

    if (client.IndexExists(defaultIndex).Exists)
        client.DeleteIndex(defaultIndex);

    client.CreateIndex(defaultIndex, c => c
        .Mappings(m => m
            .Map<Order>(mm => mm.AutoMap())
            .Map<OrderLine>(mm => mm
                .Parent<Order>()
                .AutoMap()
            )
        )
    );

    var orders = new[]
    {
        new Order { Customer = "Bilbo Baggins" },
        new Order { Customer = "Gandalf the Grey" }
    };

    var orderlines = new Dictionary<string, OrderLine[]>
    {
        { "Bilbo Baggins",
            new []
            {
                new OrderLine { ItemNumber = 1 },
                new OrderLine { ItemNumber = 2 },
                new OrderLine { ItemNumber = 3 },
                new OrderLine { ItemNumber = 4 },
                new OrderLine { ItemNumber = 5 }
            }
        },
        { "Gandalf the Grey",
            new []
            {
                new OrderLine { ItemNumber = 1 },
                new OrderLine { ItemNumber = 2 },
                new OrderLine { ItemNumber = 3 },
                new OrderLine { ItemNumber = 4 }
            }
        }
    };

    client.IndexMany(orders);

    foreach (var lines in orderlines)
    {
        client.Bulk(b => b
            .IndexMany(lines.Value, (bi, d) => bi.Parent(lines.Key))
        );
    }

    client.Refresh(defaultIndex);

    var queryResult = client.Search<Order>(s => s
        .Query(q => +q
            .HasChild<OrderLine>(c => c
                .Query(cq => +cq.MatchAll())
                // min number of child documents that must match
                .MinChildren(5)
            )
        )
    );
}

public class Order
{
    public string Customer { get; set; }
}

public class OrderLine
{
    public int ItemNumber { get; set; }   
}

查询结果仅返回Bilbo Baggins

Status: 200
{
  "took" : 5,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "failed" : 0
  },
  "hits" : {
    "total" : 1,
    "max_score" : 0.0,
    "hits" : [ {
      "_index" : "orders",
      "_type" : "order",
      "_id" : "Bilbo Baggins",
      "_score" : 0.0,
      "_source" : {
        "customer" : "Bilbo Baggins"
      }
    } ]
  }
}