2

我正在使用苦艾酒来构建 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。我什至可以拥有一个中央解析器和许多查询构建器。但我需要挂钩查询并直接解析它。

这样的事情可能吗?知道在哪里可以找到有趣的东西来解决这个问题吗?也许用苦艾酒中间件?

谢谢!

4

1 回答 1

0

我想我找到了解决办法。让我们使用一个解析器来获取用户列表。像这样的东西:

object :user_queries do
  field :users, list_of(:user) do
    resolve fn _parent, _, resolution ->
      IO.inspect(resolution.definition.selections)
      {:ok, Users.all()}
    end
  end
end

如果您使用以下嵌套查询来访问它:

{
  users {
    id
    name
    posts {
      id
      title
      text
      comments {
        id
        text
      }
    }
  }
}

您将在终端中看到一个复杂的嵌套地图。它包含我们需要的所有信息。选择包含字段。每个字段都有一个名称。如果它有一个嵌套对象,它又包含一个 list selections

现在我们只需要沿着兔子洞递归,为我们的 Dgraph 查询收集信息并相应地构建它。而且由于它已经通过了苦艾酒验证等,它看起来是一个不错的选择。

有趣的是,如果这样的方法会导致 Absinthe 附带的优化出现问题,比如在已经获取的对象的内存缓存中......</p>

于 2018-06-04T22:01:50.507 回答