在Go语言中实现GraphQL的Mutation

在这篇文章中,我将以使用Golang + MongoDB和GraphQL来尝试并且记录GraphQL的Mutation进行解释。

我将再次解释GraphQL,并将其汇总。

GraphQL 是一种查询语言和运行时环境,用于获取和修改数据。

在GraphQL中,不再像以前使用RESTful那样创建多个终点并进行通信。GraphQL只需要一个终点即可运行。

GraphQL的优点基本上是

・只需要一个终端点即可
・可以以类型安全的方式与数据库进行交互

只要牢记这两点,我认为就没有问题(如果有补充,欢迎提出)。

虽然只是简短的说明,但现在我们要谈论的是关于实施方面的事情。
尽管不是直接编写代码,我们会考虑一些概念性的东西。

GraphQL 的实现思路

首先,我希望您能以以下的感觉理解GraphQL实现的流程(我认为这个流程不仅适用于Golang,还适用于一般情况,大概)。

    1. 用GraphQL定义处理的Type(GraphQL处理数据的设置)

 

    1. 按照数据获取和创建的用途定义Field(在这里使用Type)

 

    1. 将Field组合成Schema

 

    1. 创建GraphQL请求(请求GraphQL查询数据库)

 

    1. 将Schema和请求结合起来执行GraphQL

 

    返回指定的数据

我之前写过一篇关于在Golang + MongoDB中使用GraphQL的文章,但这个请求包含了两个概念,其中一个是这篇文章标题中所述的Mutation(以下简称为”变异”)。
*虽然这个术语并非官方使用的词汇,但我觉得这样的表达更容易理解。
*在流程的第4步中提到了”与数据库查询请求”,但GraphQL并不直接与数据库进行交互(根据具体实现的方式可能会直接与数据库交互)。GraphQL仅仅是在从数据库中获取到的数据集上执行操作。例如,执行一个GraphQL查询以获取特定的用户时,实际上是针对已经从数据库中获取到的用户表的所有记录(在这里,已经转换为结构体数组)进行操作。

请求包括查询和变异。

查询(类似于以前的GET)…请求获取数据
变更(类似于以前的POST)…请求更新数据

在之前的文章中,我们解释了如何使用GraphQL查询来获取数据,现在我们将介绍如何使用Mutation来插入数据。之后我们还会继续写关于更新和删除的内容。

使用Golang语言和GraphQL技术实现Mutation操作。

我们将使用NoSQL的MongoDB数据库。

上一篇文章中,GraphQL的模式定义代码如下。

rootQuery := graphql.ObjectConfig{
  Name: "RootQuery",
  Fields: fields.UsersField,
}
schemaConfig := graphql.SchemaConfig{
  Query: graphql.NewObject(rootQuery), // Query
}
schema, err := graphql.NewSchema(schemaConfig)
if err != nil {
  log.Fatalf("failed to create new schema, error: %v", err)
}

如果使用突变,则情况如下。

rootQuery := graphql.ObjectConfig{
  Name: "RootQuery",
  Fields: fields.UsersField,
}
rootMutation := graphql.ObjectConfig{
  Name: "RootMutation",
  Fields: fields.CreateUserField,
}
schemaConfig := graphql.SchemaConfig{
  Query: graphql.NewObject(rootQuery), // Query
  Mutation: graphql.NewObject(rootMutation), // Mutation
}
schema, err := graphql.NewSchema(schemaConfig)
if err != nil {
  log.Fatalf("failed to create new schema, error: %v", err)
}

rootMutation变量被创建,并将其作为新的GraphQL对象添加到SchemaConfig的Mutation中。
*在上一篇文章中,我们在同一个文件中定义了fields,但是这次我们将其分开保存在不同的文件中,因此我们要写成fields.UsersField或fields.CreateUserField。

现在,我们来解释一下rootMutation的内容。
它并不是很复杂,可能会感觉很轻松。

rootMutation将fields.CreateUserField(在此指的是fields/user.go中的CreateUserField变量)设置为Fields。

// fields/user.go
var CreateUserField = graphql.Fields{
  "createUser": &graphql.Field{
    Type: types.UserType,
    Description: "Create new user",
    Args: graphql.FieldConfigArgument{
      "name": &graphql.ArgumentConfig{
        Type: graphql.NewNonNull(graphql.String),
      },
      "email": &graphql.ArgumentConfig{
        Type: graphql.NewNonNull(graphql.String),
      },
      "password": &graphql.ArgumentConfig{
        Type: graphql.NewNonNull(graphql.String),
      },
    },
    Resolve: func(params graphql.ResolveParams) (interface{}, error) {
      name, _ := params.Args["name"].(string)
      email, _ := params.Args["email"].(string)
      password, _ := params.Args["password"].(string)

      database.CreateNewUser(name, email, password)

      return nil, nil
    },
  },
}

当查询获取特定用户时,原本使用“user”开头,但现在改为“createUser”。
此名称将在发送请求时使用。

只需提供一个选项:
如果您能像查询一样理解Args,那就很好了。这是您在发送请求时可以指定的元素。在代码中,它们被定义为name,email和password,这意味着您可以在发送请求时设置这些元素。对于POST请求来说,这是很常见的事情。

最后的第六行database.CreateNewUser(name, email, password)是与数据库进行交互的部分。
因为这里将代码分离,所以在外部的database目录下有一个user.go文件,用于与数据库进行交互。
database/user.go的内容如下:

// database/user.go
func CreateNewUser(name string, email string, password string) {
  // connection to mongoDB
  session, _ := mgo.Dial("mongodb://localhost/test")
  defer session.Close()
  db := session.DB("test")
  // insert
  newUser := &User{
    Id: bson.NewObjectId(),
    Name: name,
    Email: email,
    Password: password,
  }
  col := db.C("users")
  if err := col.Insert(newUser); err != nil {
    log.Fatalln(err)
  }
}

如果你理解MongoDB的插入方法,阅读这段内容应该没有问题。
func (*Collection) Insert的意思是,这是一个指向Collection的指针的方法,用于插入操作。

好的,突变的处理到此为止。
突变过程中的动作就这些了。

使用已实现的突变(Mutation)进行利用。

要使用突变功能,必须发送执行该操作的请求。

查询请求如下所示。

request := `
  {
    user(id: "5c94f4d7e803694b2d09da75") {
      id
      name
      email
      password
    }
  }
`

如果将这个写成突变请求的形式,

request := `
  mutation {
    createUser(name: "name", email: "email", password: "pass") {
      name
      email
      password
    }
  }
`

由于在fields/user.go文件中,createUserField被定义为名为”createUser”的字段,因此在这里使用createUser来编写变更操作。
然后,使用该参数来指定要创建的新数据的元素。

这些元素对应于createUserField的每个参数,并且它们会通过Resolve函数传递并执行Insert操作。我觉得这个问题其实挺简单的。

如果你用mongo进入数据库并查看db.users.find()之类的命令,你会发现已经添加了创建的文档。
如果没有找到的话,请尝试搜索一下笑。

嗯,我认为一旦了解了GraphQL的工作原理,基本上就能理解大部分实现方法了。
此外,实际编写并运行代码也非常重要。

如果有任何错误的表达或描述,请毫不犹豫地指出来。

广告
将在 10 秒后关闭
bannerAds