Home > Mobile >  How to take Range GreaterThan Or LessThan on condition base in one Nest query?
How to take Range GreaterThan Or LessThan on condition base in one Nest query?

Time:08-30

I need to write one range query with different condition base

await _elasticClient.SearchAsync<T>(s => s
                            .Index(IndexName)
                            .From(From)
                            .Size(Size)
                            .Aggregations(ag => ag
                               .Cardinality("SumName", ca => ca.Field("CardinalField")))
                            .Query(q => q
                                .Bool(b => b
                                    .Must(m => m
                                            .QueryString(qs => qs                                                        .Fields("FieldNames").Query("FieldValue")),
                                          m => m.Terms(tf => tf
                                                       .Field("TermField")
                                                       .Terms("TermFeildVal")),
                                          m => m.Range(ra => ra.Field("RangeField").GreaterThanOrEquals("RangeVal")))))
                            ).ConfigureAwait(false);

How can I use GreaterThanOrEquals, GreaterThan, LessThanOrEquals & GreaterThan on the basis of my input string, e.g., if someone wants with gte, use GreaterThanOrEquals, if they want lte, use LessThanOrEquals, etc.?

Like

await _elasticClient.SearchAsync<T>(s => s
                            .Index(objFeasibilityRangeVM.IndexName)
                            .From(objFeasibilityRangeVM.From)
                            .Size(objFeasibilityRangeVM.Size)
                            .Aggregations(ag => ag
                               .Cardinality(objFeasibilityRangeVM.SumName, ca => ca.Field(objFeasibilityRangeVM.CardinalField)))
                            .Query(q => q
                                .Bool(b => b
                                    .Must(m => m
                                            .QueryString(qs => qs
                                                        .Fields(objFeasibilityRangeVM.FieldNames).Query(objFeasibilityRangeVM.FieldValue)),
                                          m => m.Terms(tf => tf
                                                       .Field(objFeasibilityRangeVM.TermField)
                                                       .Terms(objFeasibilityRangeVM.TermFeildVal)),
                                          m => m.Range(ra => ra.Field(objFeasibilityRangeVM.RangeField)
                                          FieldValue == "gte"?
                                          .GreaterThanOrEquals(RangeVal)
                                          : .LessThanOrEquals(RangeVal)
                                          ))))
                            ).ConfigureAwait(false);

CodePudding user response:

One option could be to move range part into method like this

QueryContainer Range(string condition)
{
    return condition == "gte" 
        ? new NumericRangeQuery { Field = "RangeField", GreaterThanOrEqualTo = 1 }
        : new NumericRangeQuery { Field = "RangeField", LessThanOrEqualTo = 1 };
}

and then your query becomes something like

await _elasticClient.SearchAsync<T>(s => s
    .Index(IndexName)
    .From(From)
    .Size(Size)
    .Aggregations(ag => ag
        .Cardinality("SumName", ca => ca.Field("CardinalField")))
    .Query(q => q
        .Bool(b => b
            .Must(m => m
                    .QueryString(qs => qs.Fields("FieldNames").Query("FieldValue")),
                m => m.Terms(tf => tf
                    .Field("TermField")
                    .Terms("TermFeildVal")),
                _ => Range("gte"))))
).ConfigureAwait(false);

With second idea you could inline your logic like below using the fact that in case to / from values are null NEST will omit those in generated query to Elasticsearch

var searchResponse = await client.SearchAsync<object>(s => s
    .Index("test")
    .From(0)
    .Size(10)
    .Aggregations(ag => ag
        .Cardinality("SumName", ca => ca.Field("CardinalField")))
    .Query(q => q
        .Bool(b => b
            .Must(m => m
                    .QueryString(qs => qs.Fields("FieldNames").Query("FieldValue")),
                m => m.Terms(tf => tf
                    .Field("TermField")
                    .Terms("TermFeildVal")),
                m =>
                {
                    double? gtValue = null;
                    double? ltValue = null;

                    if (FieldValue == "gte")
                    {
                        gtValue = 1;
                    }

                    if (FieldValue == "lte")
                    {
                        ltValue = 2;
                    }
                    
                    return m.Range(ra => ra.Field("RangeField").LessThanOrEquals(ltValue).GreaterThanOrEquals(gtValue));
                })))
);
  • Related