Providing complex filtering REST API [duplicate] - api

This question already has answers here:
REST and complex search queries
(5 answers)
Closed 10 years ago.
So I am building a RESTful (as RESTful as I can) API with the Laravel 4 PHP Framework. Right now I have dozens of API calls working and I have a process for being to do limit, ordering, and do simple filtering. Here would be an example of one of the calls:
/api/v1/users?limit=10&offset=10&firstName=John&order[]=createdTimestamp desc
This would return the 11th through 20th users that have a first name of John ordered by the createdTimestamp in descending order. The simple filtering here can only does exact matches (=). Now I also want to be able to provide a more complex filtering system through the REST API that supports the ability to specific the equality match type that way they could do a != or > or LIKE, etc... The issue is that I don't know if I am going to be able to provide this type of filtering through a normal query string.
What is the best way to provide this complex filtering through a REST API? Is doing through a POST still considered the best way even though it is not "truly" RESTful (even though this would prevent issues of the user trying to run a long query that exceeds the URI character length limit that some browsers have)?

#ryanzec
Now I also want to be able to provide a more complex filtering system
through the REST API that supports the ability to specific the
equality match type that way they could do a != or > or LIKE, etc...
The issue is that I don't know if I am going to be able to provide
this type of filtering through a normal query string.
It's not possible with simple query string(well, maybe it's possible but is very hard to encode such logic properly in query string). You need to define custom query format and use POST to submit such query. Server may respond with:
"201 Created" status and "Location" header field indicating query resource if there was no such query before; or
"303 See Other" and "Location" header field indicating already existing query resource.
Is doing through a POST still considered the best way even though it
is not "truly" RESTful
I do not know who said this, but it's wrong. There is nothing wrong with using POST for such purposes.

Use forms in your collection resource responses to tell the client how to search the collections. See my answer to REST and complex search queries for examples.

Related

Should vue filtering use REST API or url parameters

I'm designing a website with a REST API using Django Rest Framework and Vue for the front end and I'm trying to work out what the proper way to do filtering is.
As far as I can see, I can either:-
a) Allow filtering via the API by using URL parameters like /?foo=bar
or
b) Do all the filtering on the Vue side by only displaying the items that are returned that have foo=bar
Are there any strong reasons for doing one over the other?
The real answer to this question is "it depends".
Here are a few questions to ask yourself to help determine what the best approach is:
How much data will be returned if I don't filter at the API level?
If you're returning just a few records, there won't be a noticeable performance hit when the query runs. If you're returning thousands, you'll likely want to consider server side querying/paging.
If you're building an application where the amount of data will grow over time, it's best to build the server side querying from the get-go.
What do I want the front-end experience to be like?
For API calls that return small amounts of data, the user experience will be much more responsive if you return all records up front and do client-side filtering. That way if users change filters or click through paged data, the UI can update almost instantaneously.
Will any other applications be consuming my API?
If you plan to build other apps that consume the API, you may want to build the filtering at the API level so you don't need to recreate front-end filtering logic in every consuming application.
Hopefully these questions can help guide you to the best answer for your use case.
Whenever I come across this issue I ask myself just one question: How many items are you working with? If you're only returning a few items from the API you can easily do the filtering on the front-end side and save yourself a bunch of requests whenever the results are filtered. Also, if the result set is quite small, it's a lot faster to do it this way rather than sending off a request every time the filters change.
However, if you're working with a very large number of items, it's probably best to just filter them out in the API, or even via your database query if that's what you're working with. This will save you from returning a large number of results to the front-end. Also, filtering large numbers of items on the front-end can significantly impact performance since it usually involves looping over a collection.

best practive rest api method get with many parameters

i have question similar to this article ( Multiple optional query string parameters REST API GET ) but the given answers have 3 different opinion/answer and i dont know which one is the best practice to use, ive searched everywhere but cant find the definite answer.can someone please help me which answer is the right one and has a prove(trusted source that backing it up) that it is a best practice, sorry for bad english i hope you can understand what im saying,
The best way is to add filters in get request. Response in this post gives one example -
Best practice for filtering results from a RESTful API call?
In rest everything is a resource so if you want to filter items within same resource you can pass filter criteria along with pagination parameters. Generally only for separate resources we create a new API for optional parameters or to filter within same resource separate APIs should not be created. They are additional testing and maintenance cost.
To me answer #2 in the article makes most sense. You will be ok going with it

How to fetch results from an offset when the API doesn't support offset (HERE Maps API)

I have a search functionality that gets data from HERE API's Search endpoint. I maintain records of each search's results so I can add metadata that I need for my own purposes and also so I can provide results without always going back to HERE API. The problem I have is with paginating, specifically with providing a starting index when fetching results from HERE. Similar to how Algolia does it, I want to be able to search for a term and begin with the results at a certain index, the offset. HERE API apparently doesn't allow this at all. The closest it comes to such a feature is that it provides the URL for the next search, as described here. This is limited because it doesn't allow me to start the search results at a particular index that I specify. So essentially I want to know if there's a "standard" way of getting such functionality even when it's not provided by the API.
My own solution
The HERE API provides a size parameter that allows specifying the total number of results that I want, so I can specify a larger size than I need, and basically use code to start the results from my desired index. But this feels a bit hacky, and I wonder if there's a better/more established way of doing this.
Happy to listen to any ideas! Thanks. :)
Such a kind of an 'offset' for starting the paging after a specific number of results is indeed not supported by the Places API itself.
You have to set up a workaround within your application.

how to create a REST api for filtered data

I've been reading a lot and I understand that a REST API maps resources with HTTP verbs. That's very easy of understand when, for example, a tutorial show an example like Employee.
A PUT will be a new record (if it doesn't exist) or an update; a GET will extract a list with all employees, and a GET api.example.com/employee/12 will extract the record for the Employee with ID = 12.
But, for example, how I could map a more useful queries like "get me all the employees with a salary under 50.000, with less that 2 years at the company and with the marital status as single"?
In other words, how I could parametrize the query? Is it correct to add parameters like api.example.com/Employee?salary<50000&years<2&marital-status=single" ?
The theory:
If you add parameters to your query, they are just part of the URL. The form of the URL does not tell you anything about whether your API is RESTful. Your API with query strings is restful if it obeys the constraints described here: http://en.wikipedia.org/wiki/Representational_state_transfer and (optionally) follows the guiding principles
So as long as your query parameters don't do anything crazy like randomly change the state of some of the resources, then your API is still RESTful
The practice:
Any sensible REST API will need query parameters for the 'index' route. In practice, LinkedIn's REST API has query parameters that just select fields from someone's profile. In this case, the URLs looks completely different from yours, but still obey the principles of REST.
Your situation:
Your query strings can't contain inequalitites, only key+value pairs. You need to express it more like ?max-salary=50000&max-years=2&marital-status=single". You might also name your 'index' route differently: api.example.com/employees (plural)

Identify item by either an ID or a slug in a RESTful API

I'm currently designing an API and I came a cross a little problem:
How should a URL of a RESTful API look like when you should be able to identify an item by either an ID or a slug?
I could think of three options:
GET /items/<id>
GET /items/<slug>
This requires that the slug and the ID are distinguishable, which is not necessarily given in this case. I can't think of a clean solution for this problem, except you do something like this:
GET /items/id/<id>
GET /items/slug/<slug>
This would work fine, however this is not the only place I want to identify items by either a slug or an ID and it would soon get very ugly when one wants to implement the same approach for the other actions. It's just not very extendable, which leads us to this approach:
GET /items?id=<id>
GET /items?slug=<slug>
This seems to be a good solution, but I don't know if it is what one would expect and thus it could lead to frustrating errors due to incorrect use. Also, it's not so easy - or let's say clean - to implement the routing for this one. However, it would be easily extendable and would look very similar to the method for getting multiple items:
GET /items?ids=<id:1>,<id:2>,<id:3>
GET /items?slugs=<slug:1>,<slug:2>,<slug:3>
But this has also a downside: What if someone wants to identify some of the items he want to fetch with IDs, but the others with a slug? Mixing these identifiers wouldn't be easy to achieve with this.
What is the best and most widely-accepted solution for these problems?
In general, what matters while designing such an API?
Of the three I prefer the third option, it's not uncommon to see that syntax; e.g. parts of Twitter's API allow that syntax:
https://dev.twitter.com/rest/reference/get/statuses/show/id
A fourth option is a hybrid approach, where you pick one (say, ID) as the typical access method for single items, but also allow queries based on the slug. E.g.:
GET /items/<id>
GET /items?slug=<slug>
GET /items?id=<id>
Your routing will obvious map /items/id to /items?id=
Extensible to multiple ids/slugs, but still meets the REST paradigm of matching URIs to the underlying data model.