Elixir × GraphQL系列 ③ 添加Mutation和Subscription设置

金丹 × GraphQL系列

– Absinthe 和 Absinthe crient 的合作

这篇文章是「Elixir Advent Calendar 2022」的第22篇文章。
虽然我在东京,但我是fukuokaex的YOSUKE。

这个系列是第三部作品。
之前的部分如下。

Elixir × GraphQLシリーズ① ~ サクッとGraphQLサーバーのセットアップ ~

Elixir × GraphQLシリーズ ② ~ サクッと Abshinthe-crient Setup ~

今回は、今まで簡単に説明していた?(いや、ほとんど説明はしてない)GraphQL Serverのセットアップは完了しているので、GraphQLの説明と、その利用方法を少し解説していきます。

GraphQL是一种查询语言。

GraphQL是一种应用程序编程接口(API)之一,与REST API等不同,它通过查询来灵活地获取想要的数据,只需从一个端点获取。

如果您想更详细地了解,请参考GraphQL的学习资源。

这次的结构

よくある、GraphQLを利用した開発の構成として使われるのは、フロント側の実装を(React,VueなどのSPA)で開発し、バックエンド側をGraphQLサーバーとして開発し、1つのエンドポイントで繋いで利用する。というものだと思いますが、

今回は、フロント側を LiveView を利用して、 フロントとバックを両方 Elixirで作成する方法を試していきます。

LiveViewを活かしたいので、クエリだけでなく、ソケットを利用したステートフルな形を準備していきます。

查询和变更指什么?

GraphQL操作主要包括查询和突变两种类型。根据CRUD模型,可以将它们对应到创建、读取、更新和删除。查询代表读取操作,而其余三种操作(创建、更新、删除)则通过突变来进行处理。

我們已經在系列1和系列2中實現了查詢部分,但尚未實現變異部分,因此我們首先希望實現變異部分。

GraphQL 变更实施的步骤

向模式添加修改操作。


defmodule OpenDataQlWeb.Schema.Schema do
  use Absinthe.Schema

# 省略 #

  mutation do
    field :create_place, :place do
      arg :lat, non_null(:float)
      arg :location, non_null(:string)
      arg :lon, non_null(:float)
      arg :name, non_null(:string)
      arg :scale, non_null(:integer)
      resolve &OpenDataQlWeb.Resolvers.Community.create_place/3
    end
  end

end

创建一个解析器

defmodule OpenDataQlWeb.Resolvers.Community do
  alias OpenDataQl.Community
# 省略 #
  def create_place(_, params, _) do
    case Community.create_place(params) do
      {:error, _} -> {:error, "Could not create place"}
      {:ok, _} = success -> success
    end
  end

我们来立即试试看。
从Firefox的ADD ON中的GraphQL客户端执行一个mutation。

スクリーンショット 2022-12-12 12.05.51.png

这次我尝试了不使用变量,直接输入数值来执行突变。

mutation{
  createPlace(name: "name5", lat: 123.4, lon: 234.5, location: "name", scale: 9){
    name
	lat
    lon
    location
    scale
    id
  }
}
スクリーンショット 2022-12-12 12.03.18.png

让我们确认是否已正确插入。执行以下查询进行确认。

{
  places{
    name
    scale
    location
    lat
    lon
    id
  }
}

我已经确认我们可以正确获取到刚刚通过变异插入的数据。

スクリーンショット 2022-12-12 12.09.20.png

GraphQL 订阅的实现

GraphQL 订阅是一种在服务器内部事件中实时向客户端推送数据的方法。

客户端发送订阅以请求特定数据。当事件发生时,执行相应的操作并推送结果数据。

那么,我们可以使用套接字。使用以下命令来准备套接字。

增加插孔

$ mix phx.gen.socket User

将生成两个文件。此外,还将在以下两个文件中添加关联。

    socket "/socket", OpenDataQlWeb.UserSocket,
      websocket: true,
      longpoll: false
    import "./user_socket.js"
defmodule OpenDataQlWeb.UserSocket do
  use Phoenix.Socket
  use Absinthe.Phoenix.Socket, schema: OpenDataQlWeb.Schema.Schema #<- 追記

订阅的实施方式

在申請监视树中追加。

  def start(_type, _args) do
    children = [
# 省略 #
      {Phoenix.PubSub, [name: OpenDataQl.PubSub, adapter: Phoenix.PubSub.PG2]},
      {Absinthe.Subscription, OpenDataQlWeb.Endpoint}
    ]

在Chinese中,只需要一个选项来释义以下内容:
将Absinthe.Phoenix.Endpoint添加到Endpoing中。

defmodule OpenDataQlWeb.Endpoint do
  use Phoenix.Endpoint, otp_app: :open_data_ql
  use Absinthe.Phoenix.Endpoint #<-追加

如果您正在使用GraphiQL插件,则需要在路由器上指定socket选项。

  if Mix.env() == :dev do
    forward "/graphiql", Absinthe.Plug.GraphiQL,
      schema: OpenDataQlWeb.Schema.Schema,
      interface: :simple,
      socket: OpenDataQlWeb.UserSocket
  end

这样一来,准备工作就完成了。

终于,我想要实现和确认订阅内容,但由于可能会变得很长,所以我打算将订阅实现部分分成几个时段,再继续写下去。

由于今年的概念是快速写作,所以我打算强调持续性,不太想写太多(如果写得太繁杂,可能无法坚持下去,所以我打算今年注重持续性,轻松写作)。

bannerAds