2

I am in the process of writing a REST API spec and struggling to find the correct representation for the search functionality.

The search would typically expect 1 or 2 main (non-optional) parameters along with 10-15 optional parameters (which may or may not be filters) and hit a solr/elasticsearch implementation to get content

I have read How to design RESTful search/filtering? and http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api and tempted to expose "search" itself as a resource and do a POST with a JSON body. However it doesn't feel right (and RESTful) when a more acceptable approach is query parameters and GET

The UI this API will feed into is actually a Search website. So a typical user scenario will be user searches for something and once a list is returned, the user is able to drill down to each element/item. The item will not be a flat object. It will be a complex object with nested resources which i intend to expose by following HATEOAS.

I am not entirely sure how to proceed with this and was hoping to get some feedback/answers.

Thanks very much

EDIT

I ended up doing what is suggested here by user Qwerty RESTful URL design for search

thanks you all those who commented.

Community
  • 1
  • 1
nesh_s
  • 399
  • 4
  • 19
  • Why don't you just go with `GET /search?param1=x&param2=y`? If you know what root entity you'll be using, you could of course put that instead of `search`, e.g. `GET /users?param1=x...` – mickadoo Nov 25 '15 at 23:55
  • i was just a bit apprehensive around what this may do to the length of the url. i was hoping to use the request body to pass complex parameters. for example, i could have multiple parameters which are arrays (or comma separated ids). in which case, the endpoint url will get too long. also i wanted to use the query string to pass params related to "sort"/"order by" etc but keep the "search" params in the body. – nesh_s Nov 26 '15 at 00:04
  • Even though the url can get long, if they're all optional then I think it's not a problem. For me it makes more sense than doing a search with `POST` anyway. If it's really too much complex logic on one endpoint maybe you might consider splitting it into different resources? – mickadoo Nov 26 '15 at 00:09

1 Answers1

1

I've faced a similar problem recently and:

  1. Simple GET can be used. The length of URL should not be an issue. You also mentioned that most of the query parameters are optional so you can simply give it a try.

  2. The solution we've applied. The assumption is you need to filter api/items/ based on given parameters. One thing that can be done is to introduce a new endpoint, namely: api/items/search/ but this is not RESTful - (BTW: IMO when REST rules are to be omitted this is the best case to do that).

    The idea is to introduce a api/filters/ endpoint which will be used to create (via POST) a filter with all the parameters that can be used to filter items. Then in response you can return 201 Created along with body and filterId of newly-created filter set. When you have this filterId make a request to api/items/filterId=<someId> and you'll receive the collection of filtered items.

    Second approach is to return 303 SeeOther along with Location header just from created filter. Your client library will take care of the whole communication and it will be transparent. This approach isn't truly RESTful, however you save a call and time.

    Filters can be persistent or given some TTL. You can also easily track search history.

EDIT

I was wrong when it comes to 303 and REST - see here.

Community
  • 1
  • 1
Opal
  • 81,889
  • 28
  • 189
  • 210
  • thanks for your reply. very interesting what you have done with the api/filters endpoint. does it mean for every search request you make you end up making two http request (in essence), one to the create the filter and another to actually filter? also where do you store the created filter. not sure if this is a valid question. if not could you please elaborate on your design. thanks – nesh_s Nov 26 '15 at 14:00
  • @nesh_s, yes, two requests definitely. But depends on the status code of the first request, the second one if more or less explicit. Personally I store created filters in DB with relation to user that created particular filter. But you can store them in any temporary store - it depends only on if they will be needed later on. The whole idea is to make endpoints more RESTful. What happens with the filters on the backend side goes into background. – Opal Nov 26 '15 at 14:04
  • very helpful. thanks for your comment. i ended up doing a GET, and passing search criteria in a json whihc was then passed in the query string. – nesh_s Nov 27 '15 at 11:23