NEST Conditional filter query with multiple terms

后端 未结 3 1710
北恋
北恋 2020-12-25 14:21

I would like to do a ElasticSearch query like this:

{
    \"query\" :
    {
        \"bool\" :
        {
            \"filter\" : [
                {
                


        
相关标签:
3条回答
  • 2020-12-25 14:41
    var searchResponse = client.Search<EventData>(s => s
                .From(0)
                .Query(q => q
                        .Bool(bq => bq
                        .Filter(
                                fq => fq.Terms(t => t.Field(f => f.Client.Id).Terms(17)),
                                fq => fq.Terms(t => t.Field(f => f.Item.Id).Terms(**new[] { 34983, 35430, 35339, 35300 }**)), 
                                fq => fq.Terms(t=>t.Field(f=>f.Event).Terms("Control de Panico")),
                                fq => fq.DateRange(dr => dr.Field(f => f.DateTime)
                                    .GreaterThanOrEquals(new DateTime(2018, 07, 01))
                                    .LessThanOrEquals(new DateTime(2018, 10, 02)))
                                )
                      ))
                .Size(2000)
                .Sort(g => sortDescriptor)
                );
    
    0 讨论(0)
  • 2020-12-25 14:50

    You can create a list of filters before you make a query if you want to check conditional filters as shown below:

    var nameList = new[] {"a", "b"};
    var colorList = new[] {1, 2};
    
    var filters = new List<Func<QueryContainerDescriptor<MyDocument>, QueryContainer>>();
    if (nameList.Any())
    {
         filters.Add(fq=> fq.Terms(t => t.Field(f => f.Name).Terms(nameList)));
    }
    
    if (colorList.Any())
    {
        filters.Add(fq => fq.Terms(t => t.Field(f => f.Color).Terms(colorList)));
    }
    
    ISearchResponse<Property> searchResponse =
         elasticClient.Search<MyDocument>(x => x.Query(q => q
         .Bool(bq => bq.Filter(filters))));
    

    If you don't need to check any condition before making filter query then you can have something like that:

    ISearchResponse<MyDocument> searchResponse =
    elasticClient.Search<MyDocument>(x => x.Query(q => q
    .Bool(bq => bq
    .Filter(
            fq => fq.Terms(t => t.Field(f => f.Name).Terms(nameList)),
            fq => fq.Terms(t => t.Field(f => f.Color).Terms(colorList))
            ))));
    
    0 讨论(0)
  • 2020-12-25 14:56

    The Filter method of a bool query takes a params Func<QueryContainerDescriptor<T>, QueryContainer>[] so that you can pass it multiple expressions to represent multiple filters

    var nameList = new string[] { "name1", "name2" };
    var colorList = new string[] { "orange", "red" };
    
    client.SearchAsync<MyDocument>(s => s
            .Index("myindex")
            .Query(q => q
                .Bool(bq => bq
                    .Filter(
                        fq => fq.Terms(t => t.Field(f => f.Name).Terms(nameList)),
                        fq => fq.Terms(t => t.Field(f => f.Color).Terms(colorList))
                    )
                )
            )
    );
    

    which results in

    {
      "query": {
        "bool": {
          "filter": [
            {
              "terms": {
                "name": [
                  "name1",
                  "name2"
                ]
              }
            },
            {
              "terms": {
                "color": [
                  "orange",
                  "red"
                ]
              }
            }
          ]
        }
      }
    }
    

    NEST also has the concept of conditionless queries, that is, if a query is determined to be conditionless, then it will not be serialized as part of the request.

    What does it mean to be conditionless? Well, that depends on the query; for example, in the case of a terms query it is deemed to be conditionless if any of the following are true

    • the field doesn't have a value
    • the term values list is null
    • the terms value is an empty collection
    • the terms values list has values but they are all null or empty strings

    To demonstrate

    var emptyNames = new string[] {};
    string[] nullColors = null;
    
    client.SearchAsync<MyDocument>(s =>
    s.Index("myindex")
        .Query(q => q
            .Bool(bq => bq
                .Filter(
                    fq => fq.Terms(t => t.Field(f => f.Name).Terms(emptyNames)),
                    fq => fq.Terms(t => t.Field(f => f.Color).Terms(nullColors)))
            )
        )
    );
    

    results in

    {}
    

    Conditionless queries serve to make writing NEST queries easier in that you don't need to check if the collection has values before constructing a query. You can change conditionless semantics on a per query basis using .Strict() and .Verbatim().

    0 讨论(0)
提交回复
热议问题