Are Subqueries RESTful?

Twitter is great for one-liners, but it's very difficult to carry on any kind of advanced conversation there. Therefore when I saw this tweet yesterday, I knew I'd be picking a different medium to reply:

The blog seems like a good place, as I can put examples and all kinds other things here, and waffle at length (which is really why I like it!). Because when condensed to tweet form, the answer is really "it depends".

The Problem(s)

REST is all about representations of resources. They might come in different formats, and they might appear at their own URI as well as in one or more collections, but essentially you just get a representation of a thing. This is great, apart from when it isn't.

  • What if you want a smaller result set with only a limited number of fields?
  • What if you want related data? For every resource in a collection?

There are a couple of tactics that I deploy each time I need to solve one of these problems, but they all revolve around remodelling the resource structure. Just as we sometimes move fields around for database design or normalisation, we can do exactly the same with a RESTful service to make the resulting output make more sense to consumers. I thought I'd share examples of these tactics in this post.

More Verbose, Less Verbose

If a resource can be delivered in multiple formats, say XML or JSON, then why not in multiple "verbosities"? Sometimes you only want the outline of a resource, for example if you're display news items, you might only want the title and posting date. When you come to display that specific resource though, you'll want all the details, so you might end up with data structures like this:

Standard record:

  • Title
  • Author
  • Date
  • Excerpt

Verbose record:

  • Title
  • Author
  • Date
  • Excerpt
  • Full Article
  • Collection of Related Articles

If you want an in-the-wild example, try the Joind.in API. All the records there come in a fairly minimal format, but you can request more fields by adding verbose=yes as a GET parameter. Compare the API response (it's HTML, you can just click) for the recent DPC conference http://api.joind.in/v2.1/events/1109 with its verbose version http://api.joind.in/v2.1/events/1109?verbose=yes.

Splitting into Subresources

The alternative to allowing different verbosity of representations is to remove part of the record as it might be stored in the database into a separate resource.

So if your article is stored at http://example.com/articles/42, this would show the abbreviated version of the record from the structure above. Then you could offer the main body of the article at a separate location, such as http://example.com/articles/42/body. This does lead to repeated queries but if you only need the extra detail when you want to display a single record, it may well be worth the tradeoff - of course your mileage will vary between different applications.

Nesting Likely Data

The final tactic I want to share is where the server has a good idea that information will be needed from more than one source. There's a good example in the wild from GitHub - if you grab a list of issues over their API, you'll get the full user object of the user that created each issue. This makes sense because we'll always want to display who created the issue.

As an example, try requesting this URL with curl or your favourite API tool: https://api.github.com/repos/zendframework/zf2/issues and have a look at the structure that's returned (and as a total aside, admire the pretty-printing! I love GitHub's API)

Generic Solutions

There certainly are generic solutions, where you can basically express the select statement in URL form, but I'm not a huge fan of this approach. I'm sure there will be links to excellent resources in the comments of this article (thanks, people!)

8 thoughts on “Are Subqueries RESTful?

  1. Hi,
    thanks for this fast and very exclusive answer.

    At first i learned, that i have to write restful only with one "l". I have got a little problem with my orthography if there are no numbers ;-)

    It was very useful and helpful (oh my god, these word with one "l", too? i made it wrong my whole live.).

    But there are some more questions on it:
    Example:
    I have got articles with categories, if i am want to PUT a specific category in an specific article i would do that:
    PUT http://www.example.com/api/article/42/category {body things ...}
    But how am i able to ask for a specific catgory to all articles like:
    GET http://www.example.com/api/article/?category_name='my+category'
    that i get a subselection of my collection of articles or is that the work of client. Like "You get all, do it your self"

    this ist part of the tweet, when i asked "like couchDB does it" (or what i mean).
    There is an option to make
    GET http://couchServer.com/db_name/articles/?start_id=2&end_id=5
    to get all articles with id between 2 and 5 (please don`t hit me if it is not completely correct the way they does)
    But, they put some queries (GET params) at the end to make their request more concrete. (AS you said with ?verbose=yes)
    And they are telling:
    "couchDB has a perfect RESTful API"

    The Problem ist no problem to create a skript, that catches all these queries, but when i make some i lost the this straight way that RESTful gave my. I understand RESTful as as Service, where a normal programmer needs no real documentation. He will only need the names of the resources and is able to work on it now.

  2. My thought on modifying the query from the request would be, indeed, to use the query string. Depending on your requirements I'd use it to limit aspects of the query such as limits, columns to return, filters to apply, ordering and, possibly, depth of retrieval.

    In my mind query strings are exactly the place for that kind of output modification.

    • But are they RESTful?
      I think that they good fot those thinks, too. But is there a way/role to keep the api as simple as possible?
      I think if you know the resource you are asking for, then you know the properties of the resource, too. Than it makes sense to aks for subcollection like this
      .../collection/?property_name=example
      to get all items of the collection with property_name = example
      added with some extra things like limits, or between-things for the "id"

    • Advice from qafoo will always be good :) Hopefully between us we've helped you to make some decisions about your own API - there's never a "right" answer, as all applications are different. Hope it all goes well!

  3. Pingback: Are Subqueries RESTful? | Advanced PHP | Scoop.it

  4. Wouldn't it fit better in a RESTful architecture to use hypermedia for distinguishing between verbosity levels? Rather than adding ?verbose=yes to the URL, you could use the header Accept: vnd.example-com.foo+json; verbosity=1 or Accept: vnd.example-com.foo+json; verbosity=0 for brevity.

    Sorry for necroing, I thought it'd contribute to the post. :)

    • There are a bunch of things I might do differently next time :-) Most of all, only having two possible settings for verbosity is nonsense, I won't do that ever again. It's certainly possible to use media types as you showed in your example, lots of APIs do it this way, my example just doesn't. Comments always appreciated, don't apologise for contributing!

Leave a Reply

Please use [code] and [/code] around any source code you wish to share.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>