问题描述
我对Elixir,Phoenix和Absinthe完全陌生...所以请放轻松。 :)
我正在使用名为Dgraph的库来尝试名为Dlex的图形数据库。我编写了一个简单的查询,用于查找并返回用户列表(目前我只有两个用户):
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,"uid": null
}
]
}
}
知道我在做什么错吗?
解决方法
在我看来,您可能会在用户解析器中返回适当的数据,但有一个例外:当苦艾酒为每个用户解析字段时,default resolver仅将字段视为原子键。当在父映射中找不到:uid
,:email
或:name
时,它将返回nil
。
您可以将结果转换为以原子作为键。如果您想走那条路,一个选择就是映射每个用户并显式复制您想要的内容。
users = Enum.map(users,&%{uid: &1["uid"],email: &1["email"],name: &1["name"]})
不过,这是添加键时您还需要更新的地方。而且,对更多动态解决方案的许多尝试都没有遵循最佳实践(它们会在运行时打开应用程序以创建新原子,这是一个坏主意,或者在看到无法识别的键时抛出错误)。
我过去使用的一种解决方案是创建自己的默认MapGet中间件,该中间件同时检查原子键和字符串键。
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 docs描述了换出默认中间件。在我的应用中,这非常简单。
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,object)
end
# ...
end