Elastic Nest Passing Dynamic Values into Sort

3k Views Asked by At

I have My Elastic Query working well, I have aggregations and I have it sorting on a particular field, but if the user wants to say sort it on price, how can i dynamically change the sort field, without putting a switch statement around the entire query to select a different field.

my current query:

.Sort(ss => ss
                    .Field(f => f
                        .Field(ff => ff.DispatchTimeInDays)
                        .Order(Nest.SortOrder.Ascending)
                        )
                    )
2

There are 2 best solutions below

3
On BEST ANSWER

You can do this in the Field lambda expression

var userInput = "title";

client.Search<Question>(s => s
    .Index(Meetup.DefaultIndex)
    .Query(q => q
        .Match(m => m
            .Field(f => f.Title)
            .Query("Elasticsearch Kibana")
        )
    )
    .Sort(ss => ss
        .Field(f =>
        {
            f.Order(Nest.SortOrder.Ascending);

            switch (userInput)
            {
                case "body":
                    f.Field(ff => ff.Body);
                    break;
                case "title":
                    f.Field(ff => ff.Title);
                    break;
                default:
                    f.Field("_score");
                    f.Descending();
                    break;
            }

            return f;           
        })
    )
);

You may want to factor this out into a method so that the fluent method call doesn't grow unwieldy

client.Search<Question>(s => s
    .Index(Meetup.DefaultIndex)
    .Query(q => q
        .Match(m => m
            .Field(f => f.Title)
            .Query("Elasticsearch Kibana")
        )
    )
    .Sort(ss => ss
        .Field(f => SortFromUserInput(f, userInput))
    )
);

private IFieldSort SortFromUserInput(SortFieldDescriptor<Question> f, string userInput)
{
    f.Order(Nest.SortOrder.Ascending);

    switch (userInput)
    {
        case "body":
            f.Field(ff => ff.Body);
            break;
        case "title":
            f.Field(ff => ff.Title);
            break;
        default:
            f.Field("_score");
            f.Descending();
            break;
    }

    return f;
}
0
On

I've found that the best way to write modular queries with NEST is using the Object Initializer Syntax. You can build your query piecemeal, swapping out parts as needed.

// Can write your switch statement around just this part and even wrap it in a method
var sort = new List <ISort>
{
    new SortField 
    {
        Field = Infer<YourType>(t => t.DispatchTimeInDays),
        Order = Nest.SortOrder.Ascending
    }
};

var searchRequest = new SearchRequest(typeof(YourType))
{
    Sort = sort
    // other query details omitted
};

_client.Search<YourType>(searchRequest);