REST URL design for greater than, less than operations

66,786

Solution 1

Pagination, greaterthan and lessthan, sound like query parameter to me, since you are queries your resource with these parameters. So you should do something like:

/customers?page=1, or
/customers?page=1&gt=716, or
/customers?page=1&gt=716&lt=819

You can even limit size of page:

/customers?page=1&gt=716&lt=819&maxpagesize=100

where gt stands for greater than (same as in xml-escaping) and lt stands for less than.

Solution 2

If you have multiple parameters and need to apply some conditions for each params, I recommend you to pass a JSON object to params.

Consider you want to do a condition for id and the page:

/customers?id={"lt": 100, "gt": 30}&page={"start": 1, "size": 10}

It says that I want customers that have Id(s) less than 100 and greater than 30 in the page 1 and page number of 10.

So now simply if you want to apply another condition for other parameters, you can do it by:

/customers?id={"lt": 100, "gt": 30}&children={"lt": 5, "gt": 2}&page={"start": 1, "size": 10}

and this query means customers with Id(s) less than 100 and greater than 30, children less than 5 and greater than 2 in the page number 1 with page size of 10.

I highly recommend you to read this document about designing RESTful API: http://blog.luisrei.com/articles/rest.html

Solution 3

@Julio Faerman:

Well, the problem starts when you get multiple parameters. Imagine the query string for "Customers older than 18 and younger than 60 with more than 2 children".

You can define whatever query parameters you like, such as:

/customers?min-age=19&max-age=59&min-children=3

in my example min and max are integers and are inclusive. You can change that if you prefer. Remember, anything in the URI connotes part of the resource identifier. My personal view is that things after the ? equate to clauses in the WHERE part of an SQL query (plus ORDER BY and LIMIT, not shown here):

SELECT * FROM customers WHERE age>=19 AND age<=59 AND children>=3

Edit:
Instead of min- and max- prefixes, you could allow >, < (and maybe !) as the final character of the parameter name, so instead of min-age you have a parameter called age>, which, when combined with a value in the query string, ends up looking like age>=19 :-)
Obviously you can only use this trick when the comparison has an equals sign in it.

Solution 4

REST is an architectural style that should not be considered as specific to HTTP. The pattern of the URIs are not what makes an architecture RESTful.

With that said, you probably would want to make your URI so that these queries come as query parameters at the end of the string, e.g.

/customers?min=0&max=76

Solution 5

Here is how I have been doing it.

Let's say you have the field age which is a number.

This is what the urls would look like
Equals: /filter/age=5
Greater Than: /filter/age[gt]=5
Greater Than Equals: /filter/age[gte]=5
Less Than: /filter/age[lt]=5
Less Than Equals: /filter/age[lte]=5
Not Equals: /filter/age[ne]=5

Then when I pass these arguments to the back-end I have a script that just parses the key out and converts it to the correct filter based on the age[INSERT_OPERATOR_HERE]

Share:
66,786
Vidar
Author by

Vidar

20 years a GIS Developer. I develop mostly C# based applications, WPF and have dabbled with MVC, Blazor technologies. I also tend to use Python to get things done quickly e.g. making changes or extracting data out of Postgres databases.

Updated on July 09, 2022

Comments

  • Vidar
    Vidar almost 2 years

    I am having a bit of difficulty designing a url for a rest service that can handle requests for customers based on pagination as one type of operation or requesting greater than or less than operators as another type of operation. For example:

    Pagination:

    GET /customers/0/100
    

    This will get 100 customers for page 0.

    Greater/Less Than:

    I also need a URL design to get customers that have an id greater than n (e.g. lets say 716). How would you incorporate "greater than" or "less than" in a url. I have to bear in mind that characters ">" and "<" are illegal in urls. I think this url design looks odd:

    GET /customers/greaterthan/716
    GET /customers/lessthan/716
    

    I can't use a range as that would conflict with the pagination pattern specified above and is not a nice solution in any case e.g.:

    GET /customers/716/999999999999
    GET /customers/0/716
    

    I'm sure that I'm missing something obvious - does anyone have a better solution?

    • UVM
      UVM over 13 years
      how do you plan to implement this in real time scenario--just for curiosity
    • Vidar
      Vidar over 13 years
      it's being done using the Restlet framework in Java. Essentially, I'm querying a database for records.
  • Vidar
    Vidar over 13 years
    sorry I think I've confused everyone here - I don't mean do pagination and more than, less than operations all at the same time. Pagination is a separate function and the less/greater than is another type of function.
  • Tarlog
    Tarlog over 13 years
    It doesn't matter. Pagination and less/greater are unrelated issues. You should identify your resource. In your case the resource is customers. Both pagination and less/greater are query on the resource, but it's still the same resource. Therefore you should not try to insert your functionality in the url (path-param), but instead you should use query params. At the end your call will reach the same resource class (in java), than you can add your query params to the SQL query or something like this.
  • Vidar
    Vidar over 13 years
    How would you do greater than 76?
  • Darrel Miller
    Darrel Miller over 13 years
    Even if you put the params in the query string, you are still referring to a different resource. That's ok though. Two different resources can still render portions of the same underlying dataset. Simple rule: If it's a different URL and it doesn't redirect then it is a different resource.
  • pc1oad1etter
    pc1oad1etter over 13 years
    I would think these parameters could be optional, you could just put a 'min' parameter.
  • Nicholas Shanks
    Nicholas Shanks over 11 years
    also, you should make sure your query string params are always in the same order (assuming they are independent), otherwise /resource?a=1&b=2 is a different resource from /resource?b=2&a=1 and a cached entry for one cannot be returned for the other
  • Opentuned
    Opentuned over 11 years
    It seems Tarlog has provided a good solution here however others might find this a useful resource for API design and practice... apigee.com/about/api-best-practices/all/webcast
  • deitch
    deitch over 9 years
    I stumbled across this today. What an elegant solution. Unfortunately, it only works for IDs, not for queries, so /customers/16-25 is fine, because we know that the '-' indicates a range, but if it were query field, it wouldn't work: /customers?name=123-127 is that customers where the value of name is from 123 to 127, or customers who have the name equals the string "123-127"? No way to tell.
  • Valentin Rusk
    Valentin Rusk almost 9 years
    Seems most reliable way to stick with rest! If they use json in query - then way better to go for mongo query style and POST with x-method-override = get. Otherwise everything arrived after "?" - referred as filtering options.
  • Nicholas Shanks
    Nicholas Shanks almost 9 years
    @ValentinRusk I didn't understand that. Can you re-post it in your first language so I can translate myself? Ты русский?
  • Valentin Rusk
    Valentin Rusk almost 9 years
    Лучший выбор для REST !!! Если использовать JSON в GET, тогда лучше идти по пути стиля Mongo Query + header: x-method-override. В первом случае, все что приходит после "?" - считается фильтрами.
  • Nicholas Shanks
    Nicholas Shanks almost 9 years
    @ValentinRusk Okay, not a question, just a compliment :-) Спасибо!
  • themihai
    themihai over 7 years
    Why gt/lt instead of symbols? (<>)
  • Tarlog
    Tarlog over 7 years
    <> are special characters.
  • Shrey
    Shrey over 7 years
    I like this answer. Also check tiny range module for nodejs ( npmjs.com/package/tiny-range ) , you can use this notation as well : ~1,2,3,5~10,20~
  • Yami Odymel
    Yami Odymel over 5 years
    It looks like an GET /database?query=SELECT * FROM customers WHERE CustomerNo>=16 AND CustomerNo<=716 endpoint.