【问题标题】:Adding aggregate fields to elixir graphql将聚合字段添加到 elixir graphql
【发布时间】:2018-06-02 01:28:43
【问题描述】:

我正在使用苦艾酒和长生不老药(凤凰 1.3)。我有一个博客应用程序,其中包含用户、帖子和喜欢,并且喜欢通过用户和帖子之间的多对多关系连接。

  schema "users" do
    field :email, :string
    field :handle, :string 
    many_to_many :liked_posts, MyApp.Content.Post, join_through: "likes"
  end

  schema "posts" do
    field :title, :string
    field :content, :string 
    many_to_many :liking_users, MyApp.Accounts.User, join_through: "likes"
  end

  schema "likes" do
    belongs_to :user, MyApp.Accounts.User
    belongs_to :post, MyApp.Content.Post
  end

假设我想在后端而不是前端聚合它们。我希望:liked_by 只是对所有存在的喜欢的计数,更像是field :likes, :int,这样我就可以得到这样的回复:

{
  "data": {
    "post" : {
      "title" : "Title",
      "content" : "This is the content",
      "likes" : 7
    }
  }
}

我的对象应该是什么样子?我想做这样的事情:

  object :post do
    field :id, :integer
    field :title, :string
    field :content, :string
    field :likes, :integer, resolve: assoc(:liking_users, fn query, id, _ ->
       query |> from like in MyApp.Content.Like, where: like.post_id == ^id, select: count("*")
    )
  end

编辑 #1: 更具体地说,我想知道如何在苦艾酒对象中参数化匿名函数。我可以很容易地让对象返回一个非参数化的值:

field :somenumber, :integer, resolve: fn (_,_) -> {:ok, 15} end

但是像这样添加一个参数

field :somenumber, :integer, resolve: fn (foo,_) -> {:ok, foo} end

返回以下内容:

...
"somenumber": {},
...

如何传入对象的 id 或隐式关联的查询?

编辑#2:我已经找到了解决方案,但感觉很hacky。

  object :post do
    field :id, :integer
    field :title, :string
    field :content, :string
    field :likes, :integer, resolve: fn (_,_,resolution) ->
      {:ok, Post.getLikeCount(resolution.source.id) }
    end
  end

【问题讨论】:

  • field :likes, :integer, resolve: &Post.get_likes/3 使用自定义 Post.get_likes/3 实现应该可以。详情请见Absinthe.Schema.Notation.resolve
  • @mudasobwa 越来越近,请参阅上面的编辑
  • 您不需要使用 assoc,只需在其中放置一个返回整数的函数即可。此外, assoc 也应该可以工作。你有什么错误还是什么?
  • 您查看我提供的链接了吗?我现在没有能力检查它,但你可以试试 arity 3 和 IO.inspect 的乐趣。
  • @mudasobwa 我找到了一个 hacky 解决方案,请参阅编辑 #2。

标签: elixir phoenix-framework graphql absinthe


【解决方案1】:

在听了@mudasobwa 的建议后,我有了这个解决方案:

 object :post do
    field :id, :integer
    field :title, :string
    field :content, :string
    field :likes, :integer, resolve: fn (query,_,_) ->
      Post.getLikeCount(query.id)
    end
  end

resolution,解析器的arity 3匿名函数的第三个参数,是一个Absinthe.Resolution对象。 resolution.sourceMyApp.Content.Post 类型,其中id 指的是那个帖子。

然后我刚刚在 Post.ex 中添加了一个名为 getLikeCount/1 的函数,用于获取喜欢的数量。

  def getLikeCount (post_id) do
    query =
      from l in MyApp.Content.Likes,
        where: l.post_id == ^post_id,
        select: count("*")

    case Repo.one(query) do
      nil -> {:error, "Error getting like count for post #{post_id}"}
      likes -> {:ok, likes}
    end
  end

【讨论】:

  • Repo.one/2 可能更适合这里。另外,我不明白你为什么认为这个解决方案是 hacky。顺便说一句,根据文档,调用解析器的第一个参数应该是Post.id,不是吗?
  • 已更新。此外,arity 3 函数中的第一个变量似乎正好包含我正在寻找的内容,所以这不再让人觉得 hacky。
  • 看起来这会导致 n+1 个查询,使用数据加载器或批处理不是更好,因此不会对返回的每个帖子都执行此查询?
猜你喜欢
  • 2019-03-09
  • 2018-09-16
  • 1970-01-01
  • 2021-11-06
  • 1970-01-01
  • 2021-06-19
  • 2016-11-13
  • 2021-06-26
  • 1970-01-01
相关资源
最近更新 更多