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
Russ Cam 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
Tracy Moody 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);