Более продвинутый: ассоциируйся с эликсиром абсента

В моем блоге есть Post модель, которая имеет много Comments.

schema "post" do
  field :title, :string
  field :content, :string

  belongs_to :owner, MyApp.Accounts.User, foreign_key: :owner_id

  has_many :comments, MyApp.Content.Comment, foreign_key: :post_id

  timestamps()
end

У меня также есть связанный объект абсента.

object :post do
  field :id, :integer
  field :title, :string
  field :content, :string
  field :owner, :user, resolve: assoc(:owner)
  field :comments, list_of(:comment), resolve: assoc(:comments)
end

Запросы работают как положено.

Теперь я хочу добавить логическое значение active поле к Comments схема, чтобы я мог выполнить мягкое удаление; Я выберу только комментарии, где active == trueи я буду удалять комментарии, установив active в false,

Я добавляю поле в мою схему:

field :active, :boolean, default: true, null: false

Теперь я хочу только абсент :comments поле для возврата активных комментариев. У меня есть собственный распознаватель для этого...

field :comments, list_of(:comment), resolve: fn (query,_,resolution) ->
  query =
    from c in MyApp.Content.Comment,
      where: c.post_id == ^query.id,
      where: c.active == true,
      select: c

  {:ok, MyApp.Repo.all(query)}
end

Я боюсь, что это столкнется с проблемой N+1. Есть ли более элегантный способ сделать это?

1 ответ

Решение

Вам нужно использовать Batch Resolver Вот. Документация объясняет все подробно. Ваш запрос должен выглядеть следующим образом:

query =
  from c in MyApp.Content.Comment,
    where: c.post_id in ^post_ids,
    where: c.active == true,
    select: c

{:ok, query |> MyApp.Repo.all() |> Enum.group_by(& &1.post_id)}
Другие вопросы по тегам