Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

REST - expanding relationships

Tags:

rest

I am building an event management system. The schema is described below. The API understands these relations and returns links to related resources in the request result. For example,

GET /Events/1

    "links": {
    "Venue": "/Venues/1",
    "Tickets": "/Tickets?event_id=1",
    "Teams": "/Teams?event_id=1",
    "Registrations": "/Registrations?event_id=1"
}

Most of what I've read about REST and HATEOAS suggests this is the "right" way to do it however it is very inefficient. For example, if I want to generate a report of users and teams participating in an event it requires many requests. This is analogous to running several select queries instead of running a single join query against a DB. So my question is, should I expand the relationships and embed related resources within a resource request? This also poses a problem b/c the request above will return A LOT of data. The answer might be to stick with the relationship links and setup proper caching. Regardless, I would like your opinions.

Schema

events
    hasMany registrations
    hasMany tickets
    hasMany teams

team
    belongsTo event

ticket
    belongsTo event
    hasMany registrations

user
    hasMany registrations

registrations
    belongsTo event
    belongsTo ticket
    belongsTo user
    belongsTo team
like image 602
newb1123 Avatar asked Apr 23 '13 14:04

newb1123


1 Answers

There is nothing wrong with returning the full representation of resources in the body of another request. This can be on the verbose side though, as you mentioned.

Given that some callers of the service may only want the URIs returned but sometimes you want to reduce number of round trips across the network, i.e., you want everything in one call then, the term you are searching for is, projections.

These are different representations of your resources catered to the needs of the client.

You can specify these in a URI parameter, e.g., GET /Events/1?venueProjection=full,teamProjection=uri

And then return the projection according to what the client asked.

"links": {
"Venue": {
    "uri": "/Venues/1",
    "attr1": "value1",
    "attrN": "valueN"
},
"Tickets": "/Tickets?event_id=1",
"Teams": "/Teams?event_id=1",
"Registrations": "/Registrations?event_id=1"
}

Note: Always return the URI with your projections so that, if they aren't full, the client has easy access to the full resource later.

I suggest you do some reading around "rest projections" from Google or check out the RESTful Cookbook.

like image 144
James Avatar answered Sep 27 '22 23:09

James