I would like to do a ElasticSearch query like this:
{
\"query\" :
{
\"bool\" :
{
\"filter\" : [
{
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)
);
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
field
doesn't have a value null
null
or empty stringsTo 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().