Двунаправленные отношения и полиморфные c ассоциации в экто - PullRequest
0 голосов
/ 20 февраля 2020

У меня есть таблица с именем :issues, и мне нужно установить sh способ связать две проблемы. Я думал о создании новой таблицы с именем :links, но у меня возникли некоторые проблемы при разработке схемы Ecto из-за правил, которым я должен следовать:

1. Links should be two-way and be any of these types: ["blocked-by" | "blocking" | "relates-to"]
2. If Issue-A is blocked-by Issue-B, Issue-B should be blocking Issue-A
3. If Issue-A relates-to Issue-B, Issue-B should relates-to Issue-A 
4. Creating a link on one issue should create a link on the linked issue, following rules 1 and 2.

Что еще больше усложняет это существование других таблицы :stories, :notes, :milestones, потому что я должен иметь возможность связать запись из таблицы с записью из другой таблицы или из той же таблицы с теми же правилами, что и выше.

У меня есть Также подумал о создании таблицы для каждого типа ссылки. Например, обновленная схема для Issue будет выглядеть следующим образом:

defmodule MyApplication.Issue do
  use Ecto.Schema

  @primary_key false
  schema "issues" do
    field(:issue_id, Ecto.UUID, primary_key: true)
    has_many(:linked_issues, LinkedIssue)
    has_many(:linked_stories, LinkedStory)
    has_many(:linked_notes, LinkedNote)
    has_many(:linked_milestones, LinkedMilestone)
  end
end

, и я должен сделать то же самое для Story, Note и Milestone. Я просто запутался в том, как мне настроить свои миграции и ссылки. Я также не уверен, как таблицы объединения будут знать, какая таблица их связывает, и как я могу сделать отношения двусторонними, следуя четвертому правилу, приведенному выше.

1 Ответ

1 голос
/ 21 февраля 2020

Двунаправленные ссылки могут быть смоделированы, например, как две однонаправленные ссылки. Для обеспечения целостности данных в этом случае вам придется полагаться либо на logi c уровня приложения, либо на триггеры базы данных (последний более пуленепробиваемый, но требует более высоких затрат на обслуживание).

Необходимый здесь полиморфизм - более сложная проблема. Ecto не поддерживает ассоциации polymorphi c, как это делает RailR ActiveRecord (и подобные платформы). Намеренно, потому что это имеет свою цену: нарушенные ограничения FK (и, как следствие, снижение целостности данных) и некоторое снижение производительности (которое может быть пренебрежимо на первый взгляд, но вредит росту базы).

как минимум 3 решения, которые Ecto «предлагает» взамен:

  1. Одиночная links таблица, несколько внешних ключей.
  2. Несколько <object>_links таблиц с так называемой абстрактной схемой для Link сама
  3. одиночная links таблица с несколькими таблицами соединения «многие ко многим» (issues_links, milestones_links, ...)

Каждая из них имеет множество преимуществ и недостатки, некоторые запросы специфика c et c.

Это кратко объяснено здесь https://hexdocs.pm/ecto/Ecto.Schema.html#belongs_to / 3-polymorphi c -ассоциации , но я бы также предложил сослаться на https://pragprog.com/book/wmecto/programming-ecto - эта книга содержит целую главу (14) с подробным объяснением проблемы и всеми возможными решениями, упомянутыми выше. Было бы несправедливо просто скопировать и вставить это здесь, притворяясь моим собственным знанием:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...