I am reposting my response here from a different thread, because this is exactly the same problem:
I am currently thinking about the same problem. Please allow me to brain dump my thoughts:
We have a data structure, where an object has many children and the children have attributes that are only valid within the context of this relationship. As an example, let’s say we have a photo album, which contains many photos, and each photo can contain many likes. A like is a relationship between a photo and a user. So far so simple. But: the same photo can have different likes in different albums.
From an api perspective it would be nice to add a photo to an album by its unique photo id
POST /albums/345/relationships/photos/
{
"type": "photos",
"id": "4"
}
So we can load the photo by
GET /albums/345/photos/4
Then we can add a like by
POST /albums/345/photos/4/relationships/likes
{ "type": "users", "id": "478" }
Then photo with id: 4
has a like by user 478
in album 345
.
However in a different album, the same photo might have a different set of likes. So now we have an entity uniquely identified by an ID, but with different likes depending on the album.
From an API perspective this is not even a problem I guess. But a client would need to know that it can store the likes
of a photo
only in the context of an album
and not on the photo
object itself. Does this make sense?
To model this more explicitly, we could define a album_photo
, that is: a photo contained in an album:
POST /albums/345/photos/
{
"type": "album_photo",
"data" : {
"relationships" : {
"photo": { "type": "photos", "id": "4"},
"likes": [ { "type": "users", "id": "478" } ]
}
}
}
Then the server could respond with an opaque ID object which identifies this resource
CREATED
{
"type": "album_photo",
"id": "eyJwaG90b0lkIjoiNCIsImFsYnVtSWQiOiIzNDUifQo%3D",
"data" : {
"relationships" : {
"photo": { "type": "photos", "id": "4"},
"likes": [ { "type": "users", "id": "478" } ]
}
}
}
If the album already contains an album_photo
with a link to the same photos
entity, the server would need to either upsert the like, or better revoke the POST. Then the client could load the list of album_photos
, find the one with the right photo id
and then POST the like to its like
relationship.
So, if you don’t want to have the album_photo id
persistent on the server, it can infact be a compound value that is generated on the server, and the server knows how to convert it. Eg. {“photoId”:“4”,“albumId”:“345”} base64 encoded.
Do you guys have any thoughts on this? Somehow I don’t like either approach very much…