14

This is sort of a follow-up to someone else's question about filtering/querying a list of cars. There the recommendation for a RESTful filtering request was to put filter expressions in the query of the URI, like this:

/cars?color=blue&type=sedan&doors=4

That's fine. But what if my filtering query becomes more complicated and I need to use Boolean operators, such as:

((color=blue OR type=sedan) AND doors=4) OR color=red

That is, I want to find a four-door blue car or a four-door sedan, but if the car is red I'll take it without caring about any of the other properties.

Is there any sort of convention for providing Boolean expressions in a RESTful URI's query parameters? I suppose I could by create some new querying expression language and put it in a POST, but that seems like a heavy and proprietary approach. How are others solving this?

Community
  • 1
  • 1
Garret Wilson
  • 18,219
  • 30
  • 144
  • 272
  • Odata has logical operators though I'm not a fun of its syntax http://docs.oasis-open.org/odata/odata/v4.0/odata-v4.0-part2-url-conventions.html – themihai Jun 27 '16 at 23:36

3 Answers3

7

It is perfectly okay to use

/cars/color:blue/type:sedan/doors:4

instead of

/cars?color=blue&type=sedan&doors=4

The URL standard says only that the path should contain the hierarchical part, and the query should contain the non-hierarchical. Since this is a map-reduce, using / is perfectly valid.

In your case you need a query language to describe your filters. If I were you I would copy an already existing solution, for example the query language of a noSQL database which has a REST API.

  • I think resource query language is what you need. I think you could use it like this:

     /sthg?q="(foo=3|foo=bar)&price=lt=10"
    

or forget the default queryString parser, and like this:

    /sthg?(foo=3|foo=bar)&price=lt=10

I suggest you to read the manual for further details.

  • Since I found no other URL compatible query language (yet), I think the only other option to serialize another query language and send it in a param, like SparSQL

     http://localhost:8003/v1/graphs/sparql?query=your-urlencoded-query
    

    by marklogic7. Hydra defines a freeTextQuery in its vocab, so they follow the same approach. But I'll ask Markus about this. It's a complicated topic, since according to the self-descriptive messages constraint you should describe somewhere what type of query language you use in the URL. I am not sure about this. :S

conclusion:

In order to support ad-hoc search queries we need a standard way to describe them in the link meta-data. Currently there are only a few standards about this. The most widely used standard is URI templates which does not support nested statements, operators, etc... for what I know. There is a draft called link descriptions which tries to fill the gap, but it is incomplete.

One possible workaround to define an URI template with a single q parameter which has rdf:type of x:SearchQuery and rdfs:range of xsd:string, and create another vocab about how to describe such a x:SearchQuery. After that the description could be used to build search forms, and validate queries sent to the server. Already existing queries could be supported too with this approach, so we don't need a new one.

So this problem can be solved with vocabs or new URI template standards.

Community
  • 1
  • 1
inf3rno
  • 24,976
  • 11
  • 115
  • 197
  • I had high hopes for rql, but the "documentation" at http://persvr.org/rql/ isn't really a specification --- it's little more than a set of examples. And there is only a JavaScript implementation. (A reference implementation is a poor substitute for documentation, and is sometimes even worse.) I'm left with questions such as: How can I (or even can I?) use variables with embedded `:` characters (such as RDF prefixed variables `example:foo`)? How can I (or even can I?) use custom types? You got my hopes up, but rql doesn't seem ready for general use outside of Persevere. – Garret Wilson Sep 09 '14 at 21:35
  • I just found RQL, I'll check it, and maybe try to write a PHP parser for it for personal usage. Your question is good. We need a query language, that's for sure. Please write here a comment if you find a proper one! – inf3rno Sep 09 '14 at 22:49
  • Yep, looked at SPARQL, thanks. I'd probably have to `POST` it instead of including it in the URI query. But SPARQL turned out to be too broad for what I was wanting, focused mostly on an entire RDF triple database. – Garret Wilson Sep 09 '14 at 22:56
  • I think you can use any query language and send it in the queryString in a serialized format... All you need is a parser, and traverse + validate the output data structure to build the inner queries in your system. I cannot find other URL query language than RQL, but I googled only about an hour... – inf3rno Sep 09 '14 at 23:00
  • np :-) btw there is now a similar topic here: http://stackoverflow.com/questions/25766327/is-it-ok-for-a-rest-api-to-be-exposed-via-two-http-methods/ – inf3rno Sep 10 '14 at 14:00
  • I suggest you to follow this talk : http://lists.w3.org/Archives/Public/public-hydra/2014Sep/0041.html It might be interesting for you. I don't think currently there is a REST solution for this problem. We currently have URI templates, but they cannot be used for this kind of queries, so we need one or more new standard we can describe, build and validate ad-hoc queries with. – inf3rno Sep 10 '14 at 18:09
3

I have seen many use a query string as you have provided - much like a SQL query string.

Here are just two examples:

Mark Silverberg
  • 1,249
  • 2
  • 8
  • 21
-1

Try using 1 for true, 0 for false.

/_api/web/lists/getbytitle('XYZ')/items?$filter=Active eq 1
Harsha Vardhini
  • 692
  • 6
  • 10