110

I have an entity as below:

class Person{ String id; String name; String numberOfHands; } 

With Spring Data Rest (Gosling Release Train), I'm able to specify

localhost/Person?sort=name,asc 

for sorting name ascending. Now, in a case where I need to sort by numberOfHands descending and name ascending. I'm able to specify

localhost/Person?sort=numberOfHands,name,asc 

But, I'm not able to specify

localhost/Person?sort=numberOfHands,desc,name,asc 

Is there a way to specify multiple sort order?

4
  • 15
    Add multiple sort attributes. sort=name,asc&sort=numberOfHands,desc. Commented Oct 8, 2015 at 14:14
  • Great! that works.. But that is weird.. Except for a string being appended to URL, I'm not sure if there is a direct way of generating such URL through JavaScript.. Please let me know if I'm wrong.. Commented Oct 9, 2015 at 3:01
  • 1
    Why would it be weird that is just the way the web (or URLs) work. You can generate whatever URL you like with javascript. See stackoverflow.com/questions/24059773/…. Commented Oct 9, 2015 at 5:47
  • 2
    @M.Deinum - You might wanna turn this into an answer as it's correct. If you have trouble creating such URIs via JavaScript, blame JavaScript or the library you're using. :) Commented Oct 9, 2015 at 8:43

3 Answers 3

150

Solution (tl;dr)

When wanting to sort on multiple fields you simply put the sort parameter multiple times in the URI. For example your/uri?sort=name,asc&sort=numberOfHands,desc. Spring Data is then capable of constructing a Pageable object with multiple sorts.

Explanation

There is not really a defined standard on how to submit multiple values for a parameter in a URI. See Correct way to pass multiple values for same parameter name in GET request.

However there is some information in the Java Servlet Spec which hints on how Java servlet containers parse request parameters.

The getParameterValues method returns an array of String objects containing all the parameter values associated with a parameter name. ... - Java Servlet Spec, section 3.1

The sample further in that section states (although it mixes request and body data)

For example, if a request is made with a query string of a=hello and a post body of a=goodbye&a=world, the resulting parameter set would be ordered a=hello, goodbye, world.

This sample shows that when a parameter (a in the example) is presented multiple times the results will be aggregated into a String[].

Sign up to request clarification or add additional context in comments.

1 Comment

69

Here is how to construct the multi Sort object manually/programatically.

Sort sort = Sort.by( Sort.Order.asc("name"), Sort.Order.desc("numberOfHands")); return personRepository.findAll(sort); 

Note: This solution does not directly solve the original question asked, but may help visitors that landed on this question while searching for a solution how to sort on multiple properties from a backend perspective / in a somewhat "hardcoded" way. (this solution does not require/take any URI parameters)

6 Comments

Interesting, though I guess this will only work on the server side.
Yes, this works when you need to "hardcode" it server side. It uses the Sort class from Spring data. I have clarified the answer so it's hopefully more clear now :-)
Say I use JPQL and join across multiple tables. And I want to sort it based on two columns. One from the first table and another from second table. if I pass it as Sort.by(Sort.Direction.ASC,"first_table_col","second_table_col") , I get an exception saying "second_table_col" not found in First_table. Is it possible ?
@PimHazebroek .. That is what I ended up doing. Cleared alias names for the tables and it worked. Thanks.
Second way to construct multi sort in repository: return this.bookRepository.findAll(Sort.by("published").descending().and(Sort.by("title")).a cending());
|
2

When dynamic fields are there then you simply do match with fields and add in sorting list like.

List<Sort.Order> sorts= new ArrayList<>(); if (sort == "name" && sortingOrder.equalsIgnoreCase("DESC")) { sorts.add(new Sort.Order(Sort.Direction.DESC,"name")); } else if (sort == "numberOfHands" && sortingOrder.equalsIgnoreCase("DESC")) { sorts.add(new Sort.Order(Sort.Direction.DESC,"numberOfHands")); } return personRepository.findAll(Sort.by(sorts)); 

If you are using Pagination then directly add in PageRequest Request.

return personRepository.findPersons(PageRequest.of(pageNo, pageSize, Sort.by(sorts))); 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.