Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sort on multiple fields doesn't work #2686

Closed
SLavrynenko opened this issue Mar 24, 2017 · 3 comments
Closed

Sort on multiple fields doesn't work #2686

SLavrynenko opened this issue Mar 24, 2017 · 3 comments

Comments

@SLavrynenko
Copy link

"version" : {
"number" : "2.4.4",
"build_hash" : "fcbb46dfd45562a9cf00c604b30849a6dec6b017",
"build_timestamp" : "2017-01-03T11:33:16Z",
"build_snapshot" : false,
"lucene_version" : "5.5.2"
},

NEST version 2.4.6

I've the following code:

response = client.Search(
s => s.Query(
q => GetQueryContainer(q))
.Index(Settings.IndexName)
.Source(sfd => SourceSelector(sfd))
.From(fromRow)
.Size(pageSize)
.Sort(s1 => s1.Field("Firstname", SortOrder.Descending))
.Sort(s1 => s1.Field("Lastname", SortOrder.Descending))
);

and as I see in the logs I have sort on the field that is used in the last Sort method. If I add the new Sort method in a chain I will get sorting on that field and not on all of them:

Request that code above is provided:
{"from":0,"size":20,"sort":[{"Lastname":{"order":"desc"}}],"_source":{"include":["Firstname","Lastname"],"exclude":[]},"query":{...}}

At debugger in MS Visual Studio I see that internal Sort collection has only 1 item after each call of Sort method. So it doesnt add anything to a collection - just rewrite the only 1 item every time.

@SLavrynenko
Copy link
Author

SLavrynenko commented Mar 24, 2017

From the source code I see following:

///<summary>
		///A comma-separated list of fields to return as the field data representation of a field for each hit
		///</summary>
		public SearchDescriptor<T> Sort(Func<SortDescriptor<T>, IPromise<IList<ISort>>> selector) => Assign(a => a.Sort = selector?.Invoke(new SortDescriptor<T>())?.Value);

so, a.Sort = selector?.Invoke(..) and not a.Sort.Add(...) - is it ok?

@russcam
Copy link
Contributor

russcam commented Mar 26, 2017

It's correct @SLavrynenko; To sort on multiple fields in NEST 2.x+ is

var searchResponse = client.Search<object>(s => s
    .Query(q => q
        .MatchAll()
    )
    .Sort(s1 => s1
        .Field("Firstname", Nest.SortOrder.Descending)
        .Field("Lastname", Nest.SortOrder.Descending)
    )
);

which produces

{
  "sort": [
    {
      "Firstname": {
        "order": "desc"
      }
    },
    {
      "Lastname": {
        "order": "desc"
      }
    }
  ],
  "query": {
    "match_all": {}
  }
}

All sort expressions should be inside the one .Sort(Func<SortDescriptor<T>, IPromise<IList<ISort>>> selector); the NEST structure was changed in 2.x to better represent the structure in the Elasticsearch query DSL.

@russcam russcam closed this as completed Mar 26, 2017
@whittssg
Copy link

whittssg commented Feb 19, 2021

@russcam Is there a way to provide a list to .Sort? a bit like you can for Filter? I have checked everywhere and I cant seem to find anyway to do it apart from if i use Object Initalizer.

I thought something like this would work:

var testSort = new List<ISort>();
foreach (var option in mySortList)
{
testSort.Add(new FieldSort { Field = option.Key, Order = option.SortOrder == "ASC" ? SortOrder.Ascending : SortOrder.Descending });
} 
.Sort(testSort)

Thanks

EDIT Figured it out (maybe there should be an option to just add a list of ISort to .Sort() ?

 Func<SortDescriptor<dynamic>, IPromise<IList<ISort>>> sortList = st =>
            {
                if (queryBuilder.Sort != null)
                {
                    foreach (var option in queryBuilder.Sort)
                    {    
                        if (option.SortOrder == "ASC")
                        {
                            st.Ascending(option.Key);
                        }
                        else
                        {
                            st.Descending(option.Key);
                        }
                    }
                }
                else
                {
                    st.Ascending(SortSpecialField.Score);
                }
                return st;
            };

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants