2

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 Answers 2

7

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;
}
Sign up to request clarification or add additional context in comments.

2 Comments

Excellent again Russ, thanks sorry for the slow response been away
Would it be possible to do something similar to build a postfilter terms query?
1

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.