假设你有一个 user
类型, user
有很多 posts
. 然后想象你想要找到一个用户,并删除他们的所有帖子 . 一种方法是实现以下 mutation
字段:
field deleteAllPosts, types[Types::PostType] do
argument :user_id, types.String
resolve -> (obj,args,ctx){
posts = Posts.where(user_id:args[:user_id])
posts.each{|post| post.destroy}
}
end
然后是查询
mutation {
deleteAllPosts(user_id:1)
}
将删除ID为1的用户的所有帖子 .
在我这样做之前,我想过以不同的方式做这件事,我有任何陷阱,或者我不应该使用它的原因 .
我们的想法是为 PostType
设置 deletePost
字段,在变异上设置 findUser
字段(通常是查询字段) . 假设显然如何定义这些字段,我将进行查询
mutation{
findUser(id:1){
posts{
deletePost{
id
}
}
}
}
这是一个坏主意吗?
Edit in response to feedback :我关注的一件事是,用户原则上可以在查询中进行 deletePost
选择 . 但我'm tempted to say that that' s "their fault" . 我想说"this selection can only be made if it is inside of a mutation query",但我不想在GraphQL中使用't think that' .
为了避免XY问题,这就是为什么我热衷于使用这个想法而不是最初的想法 . 感觉更具表现力(换句话说,感觉不那么多余) . 假设在一段时间后,您决定要删除属于特定 group
的那些 users
的所有 posts
. 那么在我认为的'convention'中,你应该创建一个全新的变异字段:
field deleteAllPostsInGroup, types[Types::PostType] do
argument :group_id, types.String
resolve -> (obj,args,ctx){
posts = Group.find_by(args[:group_id]).users.map{|u| u.posts}.flatten
posts.each{|post| post.destroy}
}
end
而在我建议的约定中,你只需定义一个简单的 findGroup
字段(但你必须在变异上定义它,它不属于它),然后进行查询:
mutation{
findGroup(id:1){
users{
posts{
deletePost{
id
}
}
}
}
}
我想我真正想做的是使用查询 find 一些数据,然后 mutate the data I've found . 我不知道如何在GraphQL中执行此操作 .
Second Edit: 好像这个问题中有一个明确定义的组成部分,我已经问过here . 事实证明,这些问题中的一个能够回答另一个问题,并且可能会被关闭,但我还不知道哪个方向 .
1 回答
这基本上是代码质量问题,类似于询问DRY原则或封装的要点 .
来自https://graphql.org/learn/queries/的引用如下:
这是一个很好的约定,因为它使维护,测试和调试更容易 . 副作用,无论是有意还是无意,都可能非常难以追踪和理解 . 特别是如果你在GraphQL查询中有它们,它们可以是任意大而复杂的 . 没有什么可以阻止您同时查询和修改同一个对象及其兄弟姐妹,并通过简单的嵌套在一个查询中多次执行此操作 . 这很容易弄错 .
即使你把它拉下来,代码的可读性和可维护性也会受到影响 . 例如 . 如果您知道只有您的突变修改了数据,并且查询对它没有影响,您将立即知道从哪里开始寻找特定行为的实现 . 关于你的程序如何正常工作也更容易理由 .
如果您只编写小的,正确命名的粒度突变,那么如果您有一个在不同点更新不同数据的复杂查询,您可以更容易地推断它们的作用 .
最后但并非最不重要的是,如果您需要将工作转移给其他人,那么遵守惯例会非常有用 .
简而言之 - 所有这一切都是为了让未来的生活更轻松 .
EDIT
好的,所以我看到你要去的地方 - 你想给突变提供GraphQL查询的灵活性 . 当然,这个特殊的例子可行 . 不走这条路只会是 future . 如果
deletePost
是您将要定义的唯一操作,那么讨论这一点毫无意义 .如果's not the case, then what if you wanted to delete, let'说,5个特定的用户帖子?你会给
findGroup
提供额外的参数然后将它们传递给树吗?但那么为什么findGroup
方法必须知道你将如何处理它的结果呢?这种做法违背了灵活查询本身的想法 . 如果您还想对用户执行突变怎么办? findGroup的更多参数?如果可以通过不同的方式查询用户和帖子,例如按域分类的用户,按类别分类的帖子等,该怎么办?那里也定义相同的参数?您如何确保每次操作(特别是如果您同时执行其中一些操作),所有关系链接都会在您的数据库中正确删除?您必须想象查询和查询突变的每种可能组合以及适当的代码 . 由于查询大小无限制,最终可能很难做到 . 即使单个查询 - 突变(deletePost
)的目的是明确的,也是如此容易掌握,整体查询不会 . 很快你的查询就变得太复杂了,即使对你和你来说也很难理解'd probably begin breaking them down to smaller ones, which would only do specific mutations. This way you' d回到最初的惯例,但它是一个更复杂的版本 . 您可能最终也会定义一些常规突变 . 你会如何更新或添加帖子,例如?这会在整个地方传播你的逻辑 .如果您正在编写突变,则不会出现这些问题 . 为了更好的可维护性,这需要更多的工作 .
这些都是未来的问题(可能还有更多) . 如果这些都没有看到任何在技术上完全阻止你实现你想要的东西:]