Representing many-to-many pivot data


#1

Hi,

I’m running into a similar situation as in this thread and wanted to get some feedback on my approach. Here’s the gist:

An Appointment may have 1 or more Pets and 1 or more Services. However, each Service may or may not apply to a Pet. Here’s a real-world example of how this related: a customer chooses an appointment date, they choose the pets that are a part of the appointment and they choose all of the services. For example, appointment is on 4/23 at 2:30, Max and Lady are the pets involved, and the 30 minute walk and Medication services are selected. Both pets need to be walked, but only Lady needs medication. This last sentence is the the relation I’m trying to represent.

Representing the Pets and Services relationship with Appointment is trivial; the part that is throwing me off is how to indicate that a Pet is associated with 0 or more services. Here’s what I was thinking:

{
    "data": [{
        "type": "appointment",
        "id": "1",
        "attributes": {
            ...
        },
        "relationships": {
            "services": {
                "data": [{
                    "type": "service",
                    "id": "1"
                }, {
                    "type": "service",
                    "id": "2"
                }]
            },
            "pets": {
                "data": [{
                    "type": "pet",
                    "id": "1",
                    "meta": {
                        "services": [1]
                    }
                }, {
                    "type": "pet",
                    "id": "2",
                    "meta": {
                        "services": [1, 2]
                    }
                }]
            }
        }
    }]
}

Is there a better way to represent this?

Thanks!
James


#2

@ethanresnick any chance you can offer some clarification on this?

I wrote an addon for those using Node ORMs that automatically maps models to JSON API responses, so this is something that I’d like to not only implement for myself, but for others using the library.


#3

@jdixon04 Sorry for my delayed response.

There are a few options, basically:

  1. What you did with meta.

  2. Creating a separate resource type for the pivot table, i.e. something like:

{
    "type": "appointment",
    "id": "1",
    "relationships": {
      // optionally, pets and services could remain here as 
      // relationships, along with the new "tasks" relationship.
      "tasks": [
        {"type": "appointment-tasks", "id": "1"}, 
        {"type": "appointment-tasks", "id": "2"}
      ]
    }
  }
Then, an appointment-task resource would look like this:
```javascript
{
  "type": "appointment-tasks", 
  "id": "1", 
  "relationships": { 
    "pet": { /* pet relationship data */ }, 
    "service": { /* service relationship data */ }
}
```
  1. Restart the discussion on linking within complex attributes, which I’ve always seen as the appropriate solution for cases like this, but the discussion has languished on that post 1.0. With linking in complex attributes, you’d be able to do create a tasks attribute like this, instead of creating a whole new resource type:
{
    "type": "appointment",
    "id": "1",
    "attributes": {
      "tasks": [{
        "relationships": {
          "pet": { /* pet relationship data */ },
          "service": { /* service relationship data */ }
        }
      }, /* more tasks... */]
    },
    "relationships": {
      // optionally, pets and services could here if you want.
    }
}

#4

No worries, @ethanresnick. I’m sure you are super busy just like the rest of us. That said, I appreciate you taking the time to provide some guidance.

Given the options, it seems like option 2 may be the simplest route and fits well within what I’ve built already.

Thanks again!
James