Reputation: 41
I'm trying to design a REST-ish based Web Service to interface with a farm animal management system I am working on.
To explain the problem in detail, I have a collection of animals belonging to a farm. Each animal has its own information - such as name, ID number, breed age, etc. Therefore, I would assume a URI such as the following would suit:
/animals <- retrieve list of animals
/animals/{animal-id} <- Retrieve only one animal
/animals?breed=sheep <- Search/query
The problem arises when I try to link in other dependent resources to each animal. An animal can have a collection of weight information, as well as what I call comments (observations made for a particular animal). Each of these are dependent and only exist to that one particular animal, but are themselves a resource I want to access.
The easiest approach IMO would be to nest the resources within the animal URI:
/animals/{animal-id}/weights
/animals/{animal-id}/comments
However, I see a need to access and query the weights and comments directly, without referencing the animal. Examples in usage would be to retrieve the most recent (or all) weight(s) from all animals of a particular breed ...?breed=sheep
or even return weights/comments for a selection of individual animal ID's ...?animals={ID1},{ID2},{...}
.
Further complications arise when I want to add one comment to multiple animals at once. (please excuse my representation of a POST and JSON)
POST ....
{
"comment":"Animal moved to paddock B",
"animals":[{id1}, {id2}, ...]
}
I understand that the obvious solution to this problem would be to GET and POST (for example) to each animal that I wanted to retrieve/edit. I would prefer not to do this though, as eventually I want this service accessed from mobile devices, and therefore decreasing the number of calls seems wise.
I believe that the web standards allow CSV in the URI, so something like this could work,
/animals/{id1},{id2},{..}/weights
But, I am expecting cases where ten(s) of animals may need to be referenced at once (or queried), and that would lead to a messy and unfriendly URI.
My current perceived solution is to expose weights and comments as their own resource, which allows me to access and query them directly
/weights
/weights/{weight-id}
/weights?breed=sheep
and even post directly to the collection
POST /comments
{
"comment":"Animal moved to paddock B",
"animals":[{id1}, {id2}, ...]
}
But what would /animals/{animal-id}/weights
return? Is it even needed, or would I just reference a link to the /weights?animal={animal-id}
resource itself? But is it okay to link to a queried resource?
Am I making one redundant, or just providing "another" way to access the information?
Is there something that I am doing wrong, am I letting my database influence my service model, or am I just missing the point completely?
I am quite new to this, and have read quite a few contradicting arguments regarding these issues, and so am quite confused as to what is best for my requirements.
Thanks!
Upvotes: 4
Views: 1212
Reputation: 1292
I have had similar issues to you, but in the end we were able to remove the complexities you are getting by having specific url namespaces (so to speak) for different user types using the API.
For example it might be a farm worker client app that would perform your /weights, /comments actions (POST, PUT, DELETE etc) that you are describing, so you could keep their functionality clean via something like:
/farmworkers/comments
/farmworkers/weights
And then still keep the /animals/{animal-id}/weights
URL within some other "namespace".
Another thing to consider is embedding resources using something like the HAL format (http://stateless.co/hal_specification.html), which could allow you to embed multiple animal resources within the request etc. Hope this helps.
Upvotes: 1
Reputation: 80633
It would be better to define top level resources for your other entities if you want to address them as such (/weights
, /comments
etc). You can then POST to those endpoints in a batch fashion.
POST /comments
{
"animals" : [
{"id" : 1},
{"id" : 2},
{"id" : 3},
{"id" : 4},
],
"commentText" : "Sent to Hamburger Hamlet"
}
Note that including long lists of id's in your URL is not good design for several reasons, including that most browsers and HTML proxies have restrictions on URL length (the good rule of thumb is to try and keep URL lengths at 2083 characters in length or less).
Upvotes: 3