NEST Conditional filter query with multiple terms NEST Conditional filter query with multiple terms elasticsearch elasticsearch

NEST Conditional filter query with multiple terms


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))        ))));


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().


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)            );