简体   繁体   中英

GraphQL: Many small mutations, or one bulk mutation?

Let's say I am a user and I am editing my profile on some arbitrary app. The app let's me make a bunch of changes, and when I'm done, I click on "Save" and my profile gets updated.

What is the recommended best practice in GraphQL to handle a large update like this? As I see it, there are a few options:

A) Many small mutations . If the user changed 5 things (ie, name, email, username, image, bio) the client could fire off 5 mutations to the server.

Pros: smaller, more isolated operations.

Cons: Doesn't this defeat the purpose of "one round trip to the server" in GraphQL, as it would require... 5?

B) Many small mutations, called server-side . Rather than calling 5 mutations from the client, requiring 5 round trips, you could post a data blob to the server and have a function that parses it, and runs individual mutations on the data it finds.

Pros: One round trip

Cons: We have to add another layer to the app to handle this. The new function would get messy, be hard to test, and hard to maintain over time.

C) One large mutation . The user sends the data blob to the server via a single mutation, which sets the new data in bulk on the document rather than running individual mutations on each field.

Pros: DX; one round trip.

Cons: Since fields are being passed in as arguments, this open the application to attack. A malicious user could try passing in arbitrary fields, setting fields that shouldn't be changed (ie an isAdmin field), etc. The mutation would have to be smart to know which fields are allowed to be updated, and reject / ignore the rest.


I can't find much on the web about which way is the "right way" to do this kind of thing in GraphQL. Hoping to find some answers / feedback here. Thanks!

I'd go with the third solution, one large mutation . I'm not sure I understand your point about malicious users passing arbitrary fields : they wouldn't be able to pass fields that are not defined in your schema.

As for the server side logic, you'd have to put those smart checks anyway : you can never trust the client!

A) Many small mutations. If the user changed 5 things (ie, name, email, username, image, bio) the client could fire off 5 mutations to the server.

You can execute multiple mutations in a single request. No need to call the server multiple times.

Here's an example:

mutation {
  setUserName(name: "new_name") { ok }
  setUserEmail(email: "new_email") { ok }
}

B) Many small mutations, called server-side. Rather than calling 5 mutations from the client, requiring 5 round trips, you could post a data blob to the server and have a function that parses it, and runs individual mutations on the data it finds.

This is exactly what GraphQL does for you when you mutate multiple fields or execute multiple queries at once.

C) One large mutation. The user sends the data blob to the server via a single mutation, which sets the new data in bulk on the document rather than running individual mutations on each field.

You can still set data in bulk even if you are using multiple fields.
This would require you to, instead of updating the database directly, pass the request to a middle-ware that would build and execute a single query once all mutation resolvers are executed.

Cons: Since fields are being passed in as arguments, this open the application to attack. A malicious user could try passing in arbitrary fields, setting fields that shouldn't be changed (ie an isAdmin field), etc. The mutation would have to be smart to know which fields are allowed to be updated, and reject / ignore the rest.

You shouldn't use arbitrary variables, but instead list all allowed properties as arguments.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM