我正在使用苦艾酒来构建 GraphQL API。数据存储是Dgraph,它使用 GraphQL+ 作为查询语言。它与 GraphQL 类似,但并不完全相同。
从理论上讲,这会让我处于一个美妙的境地。类似的 GraphQL 查询
query {
user {
id
username
posts {
title
text
comments {
text
}
}
}
}
也可能只是 Dgraph 中的一个查询。它看起来几乎相同:
{
users(func: has(type_user))
{
id
username
posts {
title
text
comments {
text
}
}
}
}
图形数据库一次性加载复杂关系的能力是我想使用的。问题只是:在苦艾酒中,模式应该是可组合的。在模式中将有一个:user
对象,该对象的:posts
字段为list_of(:post
)。然后是一个:post
对象。等等。
为了帮助防止 N+1 查询,您将使用数据加载器或批量加载。
现在我可以一口气加载所有内容。例如,我可以编写一个解析器来做到这一点:
defmodule MyApp.Resolvers.User do
alias MyApp.Users
def users(_, _args, _) do
{:ok, Users.all()}
end
end
以及实际查询数据库的用户上下文
defmodule MyApp.Users do
alias MyApp.Users.User
def all do
query = """
{
users(func: has(type_user))
{
id
username
posts {
title
text
comments {
text
}
}
}
}
"""
case ExDgraph.query(conn(), query) do
{:ok, msg} ->
%{result: %{users: users}} = msg
Enum.map(users, fn x -> struct(User, x) end)
{:error, _error} ->
[]
end
end
end
这里的问题是我过度获取。我总是查询所有内容,即使我只想要一个用户列表。这可行,但在性能方面不是很好。我失去了可组合性。
如果我可以访问解析器中的查询以了解请求了哪些字段,那么解决方案是什么。然后我可以使用模式匹配来构建查询,然后将其发送到 Dgraph。我什至可以拥有一个中央解析器和许多查询构建器。但我需要挂钩查询并直接解析它。
这样的事情可能吗?知道在哪里可以找到有趣的东西来解决这个问题吗?也许用苦艾酒中间件?
谢谢!