首页 > 解决方案 > Absinthe 结果具有所有空值

问题描述

我对 Elixir、Phoenix 和 Absinthe 完全陌生……所以放轻松。:)

我正在使用一个名为 Dlex 的库来试验一个名为Dgraph图形数据库。我编写了一个简单的查询,旨在查找并返回用户列表(目前我只有两个用户):

def list_users() do
  query = """
    {
      users(func: type(User)) {
        uid
        email
        name
      }
    }
  """

  {:ok, %{"users" => result}} = Dlex.query(:dlex, query)

  IO.inspect(result)

  {:ok, result}
end

的输出IO.inspect(result)正是我所期望和想要的——我的两个用户的列表:

[
  %{"email" => "rob@example.com", "name" => "Rob", "uid" => "0x1"},
  %{"email" => "bridget@example.com", "name" => "Bridget", "uid" => "0x2"}
]

但是,当我使用 GraphiQL 运行此查询时,结果中的所有值都null出于某种原因:

{
  "data": {
    "users": [
      {
        "email": null,
        "name": null,
        "uid": null
      },
      {
        "email": null,
        "name": null,
        "uid": null
      }
    ]
  }
}

知道我做错了什么吗?

标签: graphqlelixirdgraphabsinthe

解决方案


在我看来,您可能会在用户解析器中返回适当的数据,但有一个例外:当 Absinthe 为每个用户解析字段时,默认解析器仅将字段作为原子键查找。当它在父映射中找不到:uid, :email,时,它返回。:namenil

您可以将结果转换为将原子作为键。如果你想走这条路,一个选择就是映射每个用户并明确复制你想要的。

users = Enum.map(users, &%{uid: &1["uid"], email: &1["email"], name: &1["name"]})

不过,这是您在添加密钥时需要更新的另一个地方。并且许多尝试更动态的解决方案并没有遵循最佳实践(他们打开应用程序以在运行时创建新原子,这是一个坏主意,或者当他们看到无法识别的键时抛出错误)。

我过去使用的一种解决方案是创建自己的默认 MapGet 中间件,用于检查 atom 和 string 键。

defmodule MyAppWeb.GraphQL.Middleware.MapGet do
  @moduledoc """
  Default resolver that checks for both atom and string keys.
  """
  @behaviour Absinthe.Middleware

  @impl Absinthe.Middleware
  def call(%{source: source} = info, key) do
    value =
      with :error <- Map.fetch(source, key),
           :error <- Map.fetch(source, to_string(key)) do
        nil
      else
        {:ok, value} ->
          value
      end

    %{info | state: :resolved, value: value}
  end
end

Absinthe 文档描述了更换默认中间件。在我的应用程序中,它非常简单。

defmodule MyAppWeb.GraphQL.Schema do
  use Absinthe.Schema
  # ...

  def middleware(middleware, field, object) do
    map_get = {{MyAppWeb.GraphQL.Middleware.MapGet, :call}, field.identifier}
    Absinthe.Schema.replace_default(middleware, map_get, field, object)
  end

  # ...
end

推荐阅读