GraphQL:您可以更改查询结果吗? [英] GraphQL: Can you mutate the results of a query?

查看:50
本文介绍了GraphQL:您可以更改查询结果吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以书面形式这个问题我意识到我想在GraphQL中做一些非常具体的事情,而我看不到实现它的好方法.想法是这样的:

In writing this question I realised that there is something very specific I want to be able to do in GraphQL, and I can't see a good way of implementing it. The idea is this:

GraphQL的优点之一是它使您可以进行灵活的查询.例如,如果我想在特定的 forum 的每个 user 的每个 user 的所有 posts 上找到所有的 comments 然后我可以进行查询

One of the nice things about GraphQL is that it allows you to make flexible queries. For example, if I want to find all the comments on all the posts of each user in a particular forum then I can make the query

query{
  findForum(id:7){
    users{
      posts{
        comments{
          content
        }
      }
    }
  }
} 

太好了.通常,您想要收集数据以便对其进行变异.因此,在这种情况下,也许我不想获取所有这些注释,而是想删除它们.一个幼稚的建议是在 comment 类型上实现一个 deleteComment 字段,该字段会使被调用的对象发生突变.这是不好的问题,因为该请求被标记为查询,因此它不应对数据进行突变.

which is great. Often, you want to collect data with the intention of mutating it. So in this case, maybe I don't want to fetch all of those comments, and instead I want to delete them. A naive suggestion is to implement a deleteComment field on the comment type, which mutates the object it is called on. This is bad because the request is tagged as a query, so it should not mutate data.

由于我们正在对数据进行变异,因此我们绝对应该将其标记为变异.但是随后,我们失去了进行所需查询的能力,因为 findForum 是查询字段,而不是突变字段.围绕 this 的一种方法可能是在突变类型内部重新定义您需要的所有查询字段.这显然不是一个好主意,因为您需要重复很多代码,并使 query 的功能成为 mutation 功能的严格子集.

Since we're mutating data, we should definitely tag this as a mutation. But then we lose the ability to make the query we wanted to make, because findForum is a query field, not a mutation field. A way around this might be to redefine all the query fields you need inside the mutation type. This is obviously not a good idea, because you repeat a lot of code, and also make the functionality for query a strict subset of that of mutation.

现在,我认为常规"解决方案是创建一个可以完成此任务的突变字段,而无需执行其他任何操作.因此,您定义了一个带参数的突变字段 deleteAllUserPostCommentsByForum ,并以明显的方式实现它.但是现在您已经失去了灵活性!如果相反,您决定要显式地找到 user ,并删除其所有帖子,或者只想删除其 some 帖子,则需要一个全新的突变场.与REST相比,虽然GraphQL对我很有用,但这确实感觉像是我的事情.

Now, what I regard as the 'conventional' solution is to make a mutation field which does this job and nothing else. So you define a mutation field deleteAllUserPostCommentsByForum which takes an argument, and implement it in the obvious way. But now you've lost the flexibility! If you decide instead that you want to find the user explicitly, and delete all their posts, or if you only want to delete some of their posts, you need a whole new mutation field. This feels like precisely the sort of thing I though GraphQL was useful for when compared to REST.

那么,有没有一种好的方法可以同时避免这些问题?

So, is there a good way to avoid these problems simultaneously?

推荐答案

在幕后,查询和突变之间的唯一真正区别是,如果单个操作包含多个突变,则它们将被顺序解决(一次).比并发.查询和所有其他字段会同时解析.这意味着对于这样的操作:

Under the hood, the only real difference between queries and mutations is that if a single operation includes multiple mutations, they are resolved sequentially (one at a time) rather than concurrently. Queries, and all other fields are resolved concurrently. That means for an operation like this:

mutation myOperation {
  editComment(id: 1, body: "Hello!")
  deleteComment(id: 1)
}

editComment 突变将在 deleteComment 突变之前解决.如果这些操作是查询,则它们将同时运行.同样,请考虑是否有返回对象的突变,例如:

The editComment mutation will resolve before the deleteComment mutation. If these operations were queries, they would both be ran at the same time. Likewise, consider if you have a mutation that returns an object, like this:

mutation myOperation {
  deleteComment(id: 1) {
    id
    name
  }
}

在这种情况下, id name 字段也会被同时解析( (因为即使它们作为一部分返回)突变本身,这些字段本身就不是突变.)

In this case, the id and name fields are also resolved at the same time (because, even though they are returned as part of a mutation, the fields themselves are not mutations).

查询和突变之间在行为上的差异突显了为什么我们按照惯例会为每个操作定义一个突变,并避免像您的问题所建议的那样嵌套"突变.

This difference in behavior between queries and mutations highlights why by convention we define a single mutation per operation and avoid "nesting" mutations like your question suggests.

使突变更加灵活的关键在于如何将输入传递给突变,以及随后如何在解析器中处理这些输入.无需进行 deleteAllUserPostCommentsByForum 突变,只需进行 deleteComments 突变即可接受更强大的InputType,例如:

The key to making your mutations more flexible lies in how you pass in inputs to your mutation subsequently how you handle those inputs inside your resolver. Instead of making a deleteAllUserPostCommentsByForum mutation, just make a deleteComments mutation that accepts a more robust InputType, for example:

input DeleteCommentsInput {
  forumId: ID
  userId: ID
}

您的解析器然后只需要处理可能传入的输入字段的任何组合.如果您使用的是db,则这种输入很容易转换为 WHERE 子句.如果您意识到需要其他功能,例如在特定日期之前或之后删除注释,则可以将这些字段添加到输入类型"并相应地修改解析器-无需创建新的变异.

Your resolver then just needs to handle whatever combination of input fields that may be passed in. If you're using a db, this sort of input very easily translates to a WHERE clause. If you realize you need additional functionality, for example deleting comments before or after a certain date, you can then add those fields to your Input Type and modify your resolver accordingly -- no need to create a new mutation.

实际上,您可以类似地处理创建和编辑,并使某些内容变干.例如,您的架构可能如下所示:

You can actually handle creates and edits similarly and keep things a little DRY-er. For example, your schema could look like this:

type Mutation {
  createOrUpdateComment(comment: CommentInput)
}

input CommentInput {
  id: ID
  userId: ID
  body: String
}

您的解析器随后可以检查是否包含ID-如果包含ID,则它将操作视为更新,否则将操作视为插入.当然,在这种情况下使用非null可能会比较棘手(创建可能需要 userId ,而更新则不需要),因此对于每种类型的操作具有不同的输入类型,可以说是有道理的.但是,希望这仍能说明您如何利用输入类型来使您的突变更加灵活.

Your resolver can then check whether an ID was included -- if so, then it treats the operation as an update, otherwise it treats the operation as an insert. Of course, using non-nulls in this case can get tricky (userId might be needed for a create but not an update) so there's something to be said for having separate Input Types for each kind of operation. However, hopefully this still illustrates how you can leverage input types to make your mutations more flexible.

这篇关于GraphQL:您可以更改查询结果吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆