8

The problem (or missing feature) is the lack of expression possibility between different query parameters. As I see it you can only specify and between parameters, but how do you solve it if you want to have not equal, or or xor?

I would like to be able to express things like:

All users with age 20 or the name Bosse

/users?age=22|name=Bosse

All users except David and Lennart

/users?name!=David&name!=Lennart

My first idea is to use a query parameter called _filter and take a String with my expression like this:

All users with with age 22 or a name that is not Bosse

/users?_filter=age eq 22 or name neq Bosse

What is the best solution for this problem?

I am writing my API with Java and Jersey, so if there is any special solution for Jersey, let me know.

David Berg
  • 1,958
  • 1
  • 21
  • 37
  • as I know, there is no ready to use solution for this usecase. Transfer the query in a filter attribute like you said and implement the query by parsing the filter and reacting to the parsed expression. – Simulant Nov 09 '15 at 15:18
  • You could encode these characters: https://en.wikipedia.org/wiki/Character_encodings_in_HTML – Mark Sholund Nov 09 '15 at 15:18
  • @Thevenin: Can you give an example on how I could use this? – David Berg Nov 09 '15 at 15:21
  • 1
    You probably can get some inspiration from [here](http://stackoverflow.com/q/26104394/1426227). – cassiomolin Nov 09 '15 at 16:23
  • Hmn, I know it does not answer your question but to me the whole approach seems to be overkill. Most filters can easily be implemented on client side. The only nice-to-have query operations would be alphanumeric ranges, sorting and general pagination. Many times for a client app, having complete sets of data locally is the most convenient situation as it makes it less dependent on remote services. Moreover, if such apps have to implement filtering features themselves they will be a lot more stable in case you change something! Anyway, I'm sure someone will come up with a nice solution. – Doe Johnson Dec 01 '15 at 09:32

3 Answers3

3

I can see two solutions to achieve that:

  • Using a special query parameter containing the expression when executing a GET method. It's the way OData does with its $filter parameter (see this link: https://msdn.microsoft.com/fr-fr/library/gg309461.aspx#BKMK_filter). Here is a sample:

    /AccountSet?$filter=AccountCategoryCode/Value eq 2 or AccountRatingCode/Value eq 1
    

    Parse.com also uses such approach with its where parameter but the query is described using a JSON structure (see this link: https://parse.com/docs/rest/guide#queries). Here is a sample:

    curl -X GET \
      -H "X-Parse-Application-Id: ${APPLICATION_ID}" \
      -H "X-Parse-REST-API-Key: ${REST_API_KEY}" \
      -G \
      --data-urlencode 'where={"score":{"$gte":1000,"$lte":3000}}' \
      https://api.parse.com/1/classes/GameScore
    
  • If it's something too difficult to describe, you could also use a POST method and specify the query in the request payload. ElasticSearch uses such approach for its query support (see this link: https://www.elastic.co/guide/en/elasticsearch/reference/current/search.html). Here is a sample:

    $ curl -XGET 'http://localhost:9200/twitter/tweet/_search?routing=kimchy' -d '{
        "query": {
            "bool" : {
                "must" : {
                    "query_string" : {
                        "query" : "some query string here"
                    }
                },
                "filter" : {
                    "term" : { "user" : "kimchy" }
                }
            }
        }
    }
    '
    

Hope it helps you, Thierry

Thierry Templier
  • 198,364
  • 44
  • 396
  • 360
  • Thank you for your answer. I really liked parse.com's solution, so I think I will try to implement that. If nothing better comes up I will accept your answer in a couple of days (after I make a test implementation). – David Berg Dec 02 '15 at 14:22
  • You're welcome! It's clear that using JSON to describe queries has advantages especially for Node applications ;-) – Thierry Templier Dec 02 '15 at 14:26
2

OK so here it is You could add + or - to include or exclude , and an inclusive filter keyword for AND and OR

For excluding
GET /users?name=-David,-Lennart
For including
GET /users?name=+Bossee
For OR
GET /users?name=+Bossee&age=22&inclusive=false
For AND
GET /users?name=+Bossee&age=22&inclusive=true

In this way the APIs are very intuitive, very readable also does the work you want it to do.

EDIT - very very difficult question , however I would do it this way

  GET /users?name=+Bossee&age=22&place=NewYork&inclusive=false,true

Which means the first relation is not inclusive - or in other words it is OR second relation is inclusive - or in other words it is AND

The solution is with the consideration that evaluation is from left to right.

  • I do not like this solution. Why should I add '+' when it is the default behavior? What does `inslusive=true` mean? My guess is that it means that I want an `or` between the query parameters before. What if I would like to express both `and` and `or` in the same statement? I could misunderstand your answer, in that case please clarify. – David Berg Nov 10 '15 at 07:16
  • The `+` symbol is (sometimes) used to encode a space so I would not give it a meaning. See also [this question](http://stackoverflow.com/questions/1634271). – lefloh Nov 11 '15 at 08:17
  • If I consider `+` as the default behavior and only use `=` it would be ok. The remaining question is still how I express something like `(x == 1 || x == 2) && y == GURP` with this solution. – David Berg Nov 11 '15 at 12:09
0

Hey it seems impossible if you go for queryparams... If it is the case to have advanced expressions go for PathParams so you will be having regular expressions to filter.

But to allow only a particular name="Bosse" you need to write a stringent regex.

Instead of taking a REST end point only for condition sake, allow any name value and then you need to write the logic to check manually with in the program.

tech.yenduri
  • 586
  • 5
  • 7