Ссылка на составной ключ в ассоциации «own_to» в Ecto? - PullRequest
1 голос
/ 07 мая 2020

Я пытаюсь смоделировать одну сущность A как доступную только для добавления с другой дочерней сущностью, которая ссылается на первую. Итак, A имеет структуру вроде (отсортировано по inserted_at DESC):

|  id  |  version  |  column | inserted_at |
|------|-----------+---------|-------------|
|   5  |     2     |  "baz"  | 2020-04-20  |
|   3  |     2     |  "zoot" | 2020-04-20  |
|   3  |     1     |  "bar " | 2020-04-18  |
|   5  |     1     |  "foo"  | 2020-04-10  |

(id, version) образует первичный ключ для A (можно было бы сделать и (id, inserted_at), но разработчик решил, что номера версий больше читаемый).

Теперь B принадлежит A, и каждый B будет соответствовать ровно одной (id, version) паре A. Итак, что-то вроде:

|  id  |  a_id | a_version |  column | inserted_at |
|------|-------+-----------+---------+-------------|
|   4  |   5   |    2      |  "pigs" | 2020-05-05  |
|   3  |   5   |    2      |  "goats"| 2020-05-03  |
|   2  |   5   |    1      |  "rams" | 2020-05-02  |
|   1  |   3   |    1      |  "bears"| 2020-04-18  |

мой вопрос: как я могу смоделировать их с помощью Ecto Schemas ? Думаю, я знаю из чтения документов, как выглядит схема A, за исключением has_many:

defmodule MyASchema do 
  use Ecto.Schema

  @primary_key false
  schema "table_a" do
    field :id, :id, primary_key: true
    field :version, :integer, primary_key: true
    field :column, :string
    field :inserted_at, :utc_datetime
    has_many :bs, MyBSchema  # what goes here for :foreign_key?
  end
end

Но схема B (особенно belongs_to) мне менее ясна:

defmodule MyBSchema do 
  use Ecto.Schema

  @primary_key
  schema "table_b" do
    field :id, :id, primary_key: true
    field :column, :string
    field :inserted_at, :utc_datetime

    # how does belongs_to work here? would it be 
    #
    # belongs_to :a, MyASchema, primary_key: [:id, :version]
    #
    # or 
    #
    # belongs_to :a, MyASchema, define_key: false
    # field :a_id, :id
    # field :a_version, :integer
    #
    # ? If so, how could I query such that the :a field of the
    # struct is populated?
  end
end

Рад прояснить дальнейшее, спасибо за чтение + любая помощь ?

1 Ответ

1 голос
/ 07 мая 2020

Согласно форуму Elixir , Ecto не поддерживает составные внешние ключи при работе с ассоциациями.

Одним из решений было бы добавить «обычный» уникальный первичный ключ (например, автоматический -incrementing integer или UUID) и основывать ссылки на этом идентификаторе. Иногда вы утешаетесь при работе с уровнями абстракции базы данных, потому что отношения легче определить, когда база данных имеет простой первичный ключ из одного столбца (т.е. не составной).

Если изменение схемы базы данных невозможно, тогда вам нужно будет вручную разрешить ассоциации в вашем коде. Возможно, вам потребуется настроить несколько транзакций, как указано в этом сообщении .

...