In a lot of cases we have mutations where there is a one-to-many or many-to-many association we need to mutate, and where the association is exposed to queries as a paginated list.
There are a handful of critical requirements:
- Clients must be able to delete, add, and update elements of the association
- In some cases, the ordering of the association is important in which case clients must be able to reorder the elements as well
Less critical:
- Clients should be able to specify the association at the creation of the parent (e.g. create an ordered set of variants at the same time as creating the product)
- Clients should be able to delete, add, update, and reorder elements of the association at once with some form of transactional atomicity
- Clients should not have to paginate through the entire current association in order to add or remove a single element
There's a number of possible solutions to this problem:
Option 1 - Single Input Field, No Additional Mutations
The input type has a single array input field which represents the total truth of the association (new elements are added, existing elements are updated, missing elements are deleted, and order is preserved when necessary).
Cons: Deletion is very implicit. Clients have to paginated through the entire current state of the association. Not granular.
Option 2 - Single Input Field with Positions, Delete Mutation
The input type has a single array input field which is used to update existing elements and add new ones (missing elements are ignored). A position or index value can be specified on elements to reorder them. A separate mutation is used to delete elements.
Cons: It is inconsistent for deletion to be off on its own in a mutation while all other operations are on the parent. Not very granular.
Option 3 - Single Input Field, Delete and Reorder Mutations
The input type has a single array input field which is used to update existing elements and add new ones (missing elements are ignored). Separate mutations are used to delete and re-order elements.
Cons: Clients cannot add new elements to specific locations in the association, they would have to be added and then reordered separately. Not very granular.
Option 4 - Single Input Field, Add/Delete/Reorder Mutations
Like option 3 except the input field is only used for updates; a separate mutation is used for adding new elements.
Cons: Clients have to make multiple mutations to perform complex updates. Clients cannot create the parent with initial associations.
Option 5 - Entirely Separate Mutations
The parent input type has no related fields, everything is done via four separate mutations for add/remove/update/reorder.
Pros: Very explicit and granular, keeps different data model objects separate. Cons: Clients have to make multiple mutations to perform complex updates. Clients cannot create the parent with initial associations.
Option 6 - Two Input Fields with Positions
The input type has two array fields: one used to update, add, and reorder elements (see option 2) and the other to delete.
Cons: Feels like we're polluting the parent mutation; not granular.
Option 7 - Two Input Fields, Reorder Mutations
Like option 6, except a separate re-order mutation is used instead of position arguments.
Cons: Inconsistent for reorder to be off on its own. Also see cons for option 6.
All these options seem to have drawbacks. Option 5 seems to be to most explicit, but requires the user to use multiple mutations at the same time, where the operation is not really atomic anymore.
What is Facebook's way of handling those types of mutations? What is your way ? Thanks!