Предварительно загрузить все связанные записи, используя ecto - PullRequest
1 голос
/ 12 марта 2019

У меня есть связанная структура списка типа

defmodule Data.Record do
  use Data.Web, :model

  alias Data.{Record, Repo}

  schema "records" do
    field(:date_start, :date)
    field(:date_end, :date)
    field(:change_reason, :string)
    field(:is_active, :boolean, default: true)
    field(:notes, :string)
    belongs_to(
      :changed_from,
      Data.Record,
      foreign_key: :changed_from_id
    )

    belongs_to(
      :changed_to,
      Data.Record,
      foreign_key: :changed_to_id
    )

    timestamps()
  end
end

Но проблема в том, что нам нужно, чтобы все вложенные записи были загружены динамически.Например, список может записывать1зменен_ в -> запись2 изменен_ в -> запись 3 изменен_ в.Но ecto не / не может предварительно загружать динамически, например, record |> preload([{:changed_to, :changed_to}])

Каков наилучший способ / обходной путь для предварительной загрузки всех связанных changed_to записей?

1 Ответ

1 голос
/ 13 марта 2019

Ну, самый (грязный) обходной путь будет примерно таким. Он строит аргументы для preload на определенную глубину:

def preload_args(relation, max_level \\ 50) do
  preload_args(relation, max_level - 1, relation)
end

defp preload_args(_relation, level, acc) when level <= 0, do: acc
defp preload_args(relation, level, acc) do
  preload_args(relation, level - 1, [{relation, acc}])
end

Чтобы использовать это:

Repo.preload record, Record.preload_args(:changed_to)

Это будет предварительно загружать каждое :changed_to отношение к определенному уровню или до тех пор, пока их больше не будет. Конечно, это не то решение, которое вы действительно хотели бы использовать, потому что оно выполняет запрос для каждой предварительной загрузки, и вы не знаете, как долго будет работать цепочка, может быть намного больше, чем 50 шагов.

(пожалуйста, не поджаривайте меня за этот код / ​​предложение, вы специально попросили обходные пути тоже.;)

Я думаю, что этот комментарий о 'закрывающей таблице' от Aetherus, который указал мне на эту статью , вероятно, приведет вас к лучшему решению. Это также усиливает моё предположение, что вам не нужно хранить родительские и дочерние идентификаторы в первую очередь, достаточно одного parent_id. Это также облегчит вставку новой записи: вам также не нужно обновлять родительский элемент.

...