如何在 GraphQL 中执行突变?

Posted

技术标签:

【中文标题】如何在 GraphQL 中执行突变?【英文标题】:How to execute a mutation in GraphQL? 【发布时间】:2019-02-21 18:31:34 【问题描述】:

在 GraphQL 中,我们基本上有两种类型的操作:查询和突变。虽然文档中对查询进行了很好的描述并且有很多示例,但我很难理解如何执行突变。突变显然是更新方法。

我创建了非常简单的 Node.js 服务器:

var express = require("express");
var graphqlHTTP = require("express-graphql");
var graphql = require("graphql");
var inMemoryDatabase = require("./inMemoryDatabase").inMemoryDatabase;
var _ = require("lodash-node");

var userType = new graphql.GraphQLObjectType(
  name: "User",
  fields: 
    id:  type: graphql.GraphQLString ,
    name:  type: graphql.GraphQLString 
  
);

var queryType = new graphql.GraphQLObjectType(
  name: "Query",
  fields: 
    user: 
      type: userType,
      args: 
        id:  type: graphql.GraphQLString 
      ,
      resolve: function(parent,  id ) 
        return _.find(inMemoryDatabase,  id: id );
      
    
  
);

var mutationType = new graphql.GraphQLObjectType(
  name: "Mutation",
  fields: 
    user: 
      type: userType,
      args: 
        id:  type: graphql.GraphQLString ,
        name:  type: graphql.GraphQLString 
      ,
      resolve: function(parent,  id, name ) 
        var index = _.findIndex(inMemoryDatabase,  id: id );
        inMemoryDatabase.splice(index, 1,  id: id, name: name );
        return _.find(inMemoryDatabase,  id: id );
      
    
  
);

var schema = new graphql.GraphQLSchema(
  query: queryType,
  mutation: mutationType
);

var app = express();
app.use(
  "/graphql",
  graphqlHTTP(
    schema: schema,
    graphiql: true
  )
);

var port = 9000;
if (process.env.PORT) 
  port = process.env.PORT;


app.listen(port);
console.log("Running a GraphQL API server at localhost:" + port + "/graphql");

内存数据库只是在用户对象数组id, name中:

var inMemoryDatabase = [
  
    id: "31ce0260-2c23-4be5-ab78-4a5d1603cbc8",
    name: "Mark"
  ,
  
    id: "2fb6fd09-2697-43e2-9404-68c2f1ffbf1b",
    name: "Bill"
  
];

module.exports = 
  inMemoryDatabase
;

执行查询以通过 id 获取用户如下所示:


 user(id: "31ce0260-2c23-4be5-ab78-4a5d1603cbc8")
  name
 

更改用户名会是什么样子?

【问题讨论】:

【参考方案1】:

嘿,可能完全没听懂你在说什么,但我看待突变的方式是这样的

我得到了一些参数和一个字段,这与 params 和一个静态路径相同,我做了一些事情(在你的情况下,查找用户并根据传入的参数更新属性 之后,我从 resolve 函数返回一些内容,该函数将满足您在突变的 type 中指定的类型

var mutationType = new graphql.GraphQLObjectType(
  name: "Mutation",
  fields: 
    user: 
      // You must return something from your resolve function 
      // that will fulfill userType requirements
      type: userType,
      
      // with these arguments, find the user and update them
      args: 
        id:  type: graphql.GraphQLString ,
        name:  type: graphql.GraphQLString 
      ,
      // this does the lookup and change of the data
      // the last step of your result is to return something
      // that will fulfill the userType interface
      resolve: function(parent,  id, name ) 
        // Find the user, Update it
        // return something that will respond to id and name, probably a user object
      
    
  
);

然后将其作为上下文,传递一些参数并请求回用户

mutation updateUser 
  user(id: "1", name: "NewName") 
    id
    name
  

在正常的生产模式中,您通常还会有类似 errors 的内容,可以返回以传达失败/未找到更新的不同状态

【讨论】:

GraphQL 有内置的错误报告,如果突变失败,你通常会返回一个字段错误;它根本不会在架构中专门编码。 嗨大卫,我想这真的取决于你想要的错误级别。 Graphql 将为模式错误或无效查询等提供基本信息,但如果您想要更丰富的错误,这些错误等同于您从休息中得到的信息(如 422 或某些特定的失败事件),您必须为此返回一个新类型.另一个具体的例子是绑定到一个验证框架,比如在 rails ActiveModel::Validations 中,这样错误就会“更好”并且更容易被客户端使用。 在 Ruby 中,我倾向于使用graphql-ruby.org/errors/execution_errors.html(也描述了与语言无关的 JSON 错误响应格式)来返回字段或突变级别的错误。 啊,我的错,更新了 :) 有时只是将这些放在 graphiql 或 graphqlplayground 中,虽然你会出现拼写错误【参考方案2】:

@Austio 的答案非常接近,但正确的方法是:

mutation updateUser 
  user(id: "31ce0260-2c23-4be5-ab78-4a5d1603cbc8", name: "Markus") 
    id
    name
  

【讨论】:

以上是关于如何在 GraphQL 中执行突变?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 sangria-graphql 中执行突变?

如何在突变 graphQL Playground 中传递变量?

Graphql 突变返回 Post 400 错误,不知道如何解决

如何使用 GraphQL 突变进行更新(热巧克力)

如何决定用于 GraphQL 突变的根值

如何在 python 函数中编写 graphQL 突变?