14

Here's an example to set up my question. I have a model which contains 'boxes', and they have a REST endpoint:

/boxes, /boxes/{boxId}

This model also contains 'nodes':

/nodes, /nodes/{nodeId}

Nodes can sit on the borders of boxes, and this is a many-to-many type of relationship. Having one node sit on multiple borders is a way to indicate that those borders (partially) overlap, but nodes also have other purposes.

a quick visual example of boxes and nodes

I'm trying to determine how to model this in an non-surprising, RESTful way. I can see a couple of ways to do this. But I'm not sure which I should use:

  1. Model /borders as a fully fledged entity type with its own endpoint. Have boxes reference four borders (top, bottom, left, right). Have borders reference a list of nodes. Have nodes reference a list of borders.

  2. Model /boxNodeRelationships with its own endpoint, and have each such relationship point to a box, a node, and contain a 'border' field (an enum with four options).

Both are similar, and rather 'heavy' for their purpose. The alternative is to be a bit more ad-hoc:

  1. Give boxes a list of { border, node } objects. Give nodes a list of { box, border } objects. These objects would be returned from GET calls and expected from POST/PUT calls, but would not be fully fledged types with an endpoint.

I'd like to know how a RESTifarian would solve this, as well as hear some pros / cons of these approaches. I'd also like to know if there are other approaches that are fundamentally different.

mhelvens
  • 4,225
  • 4
  • 31
  • 55
  • To find the most optimal way to model the API you need to understand use cases for which it's most likely to be used. – astreltsov Sep 09 '15 at 16:02
  • @astr: We need all kinds of ways to approach this data, really, e.g. getting all nodes on a border, getting all boxes connected to a node, getting all boxes connected to another box, etc. So I'm wondering about the most elegant RESTful API that provides full access to the data. – mhelvens Sep 09 '15 at 16:32

1 Answers1

4

I would create 3 entities:

  • Box
  • Border
  • Node

And the relationships:

  • A Box can have n Borders
  • A Border can have n Nodes

So you could address them:

To get the first node: /boxes/1/borders/1/nodes/1

You could have some logic:

if /boxes/1/borders contain /nodes/1 and /boxes/2/borders contain /borders/1 then they intersect

And so on.

ACV
  • 9,964
  • 5
  • 76
  • 81
  • This is indeed one of the possibilities I considered and listed in my question. But what is the advantage of this approach over the other approaches? Would this be 'standard' in some sense? – mhelvens Sep 04 '15 at 07:39
  • How is option 2 against HATEOAS? It's actually a [common technique](http://stackoverflow.com/q/6324547/681588) for many-to-many relationships, as far as I can tell. The disadvantage of option 1 is that 'border' is a relatively useless entity; an extra redirection just for the purpose of solving this problem. They all have pros and cons. I was hoping for an expert's comparative analysis. – mhelvens Sep 04 '15 at 09:00
  • In my opinion relationships shouldn't be exposed as web service endpoints as separate entities (/boxNodeRelationship). These are not entities per se. These are not business objects. – ACV Sep 11 '15 at 09:33
  • Sure, not as end-points of themselves, perhaps. But the idea would be to have, e.g., `/nodes/{id}/boxNodeRelationships` and `/boxes/{id}/boxNodeRelationships`. (Making them available as endpoints would be optional, I guess, for completeness sake.) – mhelvens Sep 11 '15 at 12:26
  • I personally don't like this design. Why not `/nodes/{id}/box` - will return all boxes for the `id` node? – ACV Sep 11 '15 at 12:54
  • Because then I don't know which border of the box that node is attached to (one of four possibilities). – mhelvens Sep 11 '15 at 13:01