Search code examples
restentity-relationshiprestful-architecturerestful-urlnested-resources

What's the "right" way to create a many-to-many relationship in a Restful API


I try to find the best practice in order to create a Many-to-Many relationship in a Restful API. The usecase is really simple, but i cannot really found the "right" way to do it.

In our model, we have Kid that are related with a Many-to-Many relationships to Guardian. In the relationship table, we have 2 extra parameters, type (parent, nanny, emergency, etc.) and active (Boolean).

You can only add Guardian to a existing Kid, but an existing Guardian can be link with another Kid.

Today, we do it like that

POST kids/{kidID}/guardians
{
    "type": "parent"
    "active": false 
    "guardian": {
        "first_name": "foo"
        "last_name": "bar"
    }
}

This create the Guardian and add it to the Kid. But, with this method we cannot handle the case where I want to add an existing Guardian to a Kid. Here the answers I found in order to represent this, but I don't know which one is the best (and restful) way (maybe none of them are good...) :

Solution 1 - Keep the endpoint as today

But put an non-mandatory id field to the guardian. If id is empty, the API have to create the ressource otherwise is just retrieve it and update values if need.

POST kids/{kidID}/guardians/
{
    "type": "parent"
    "active": false 
    "guardian": {
        "id": "ab65f263-dd3d-bbc6-8b7b-57a3b4b26c21"
    }
}

Solution 2 - Break this endpoint in 2 calls

# Create the Guardian
POST guardians/
{
    "first_name": "foo"
    "last_name": "bar"
}

# This method can only "link" the models
POST kids/{kidID}/guardians/
{
    "type": "parent"
    "active": false 
    "guardian_id": "ab65f263-dd3d-bbc6-8b7b-57a3b4b26c21"
}

[Edited] Solution 2.5 - Create the relationship with a PUT

As before, you have to create the guardian, but in order to add the relationship you make a

PUT kids/{kidID}/guardians/{guardianID}
{
    "type": "parent"
    "active": false 
}

Subsidiary solution : In the second choice we can change the URI of the ressource by:

POST kids/{kidID}/kid-guardians/

Because it doesn't really POST a "guardian" ressource, but a kid-guardian ressource (the relationship). I don't really like it because with the old URI we can assume more easily that

GET kids/{kidID}/guardians/

Will give you all Guardians related with the Kid, but not that

DELETE kids/{kidID}/guardians/{guardianID}

Will delete the relationship and not the Guardian.

So as you understand, i'm really lost and would appreciate your help.

Best regards,


Solution

  • Would not be possible to create a third category of resource for the relationship itself, such as "guard", not subordinated to an instance of the other resources? It seems to be the recommended and usual way to deal with n to n relationships in databases.

    GET /guards?kid="Johnny" would give you a list of relationships which you could use to get all its guardians from. GET /guards?guard="Kelly", you can guess it. /kids and /guards would keep the data about the resources themselves only and would probably be easier to maintain than if you have to keep relationship data as part of them.

    I think that you could get this more RESTful by using links to each member of the relationship instead of numerical IDs. And you can have a field like "relationships" in the kids and guardians representations with the URL+querystring needed to retrieve their specific "guards" could somebody need them.