#elixir #ecto
#elixir #ecto
Вопрос:
Допустим, у меня есть User
модель, которая has_many
Post
.
Я выбрал пользователя:
user = Repo.get(User, 1)
и теперь я хочу получить все сообщения для этого пользователя. Единственное решение, которое я нашел, это:
posts = Repo.preload(user, :posts).posts
Но это некрасиво. Есть ли какое-либо сокращение для этого?
Ответ №1:
user = Repo.get(User, 1) |> Repo.preload([:posts])
Комментарии:
1. Хотя этот код может ответить на вопрос, обычно считается хорошей практикой добавлять объяснение того, что делает ваш код. Это позволяет разработчикам, которые не разбираются в этой области, понять, что происходит в коде, и помогает им научиться самостоятельно решать проблему в будущем.
Ответ №2:
Вы можете использовать Ecto.assoc/2
, чтобы получить запрос для всех сообщений, а затем передать Repo.all/1
его, чтобы фактически получить их:
iex(1)> user = Repo.get(User, 1)
iex(2)> Ecto.assoc(user, :posts)
#Ecto.Query<from p in MyApp.Post, where: p.user_id == ^1>
iex(3)> Ecto.assoc(user, :posts) |> Repo.all
[debug] QUERY OK source="posts" db=2.4ms
SELECT p0."id", p0."title", p0."user_id", p0."inserted_at", p0."updated_at" FROM "posts" AS p0 WHERE (p0."user_id" = $1) [1]
...
Комментарии:
1. В чем разница между
assoc
иpreload
?2.
assoc
создает запрос для конкретной ассоциации без извлечения данных из БД,preload
извлекает данные из БД для ассоциации, включая вложенные ассоциации.3. Обратите внимание, что
preload/2
возвращает как родительскую запись (в данном случае пользователя), так и связанные записи (сообщения) в одной структуре данных, в то времяassoc/2
как piped toRepo.all
возвращает только связанные записи (сообщения). Это означает, что если вам нужна родительская запись, вы можетеget
использовать их отдельно (как в примере выше), но у вас не будет этих данных, если вы запишете их полностью в виде конвейерных операторов.4. В случае, если ассоциация уже была загружена,
Repo.preload/2
не будет пытаться перезагрузить ее.
Ответ №3:
user = Repo.get(User, 1) |> preload(:posts)
Это сокращение для вашего случая