Как создать условное соединение в Ecto Query?

у меня есть 2 модели - User и ApiKey (user has_many api_keys), и я пытаюсь создать условное соединение. Я имею в виду, что я хотел бы загрузить пользователя с одним запросом с его активными ApiKeys. Мой текущий код выглядит так

query = from u in User, 
        join: a in assoc(u, :api_keys), 
        where: u.email == ^email,
        preload: [api_keys: a]
user = Repo.one(query)
Repo.preload user, api_keys: (from a in ApiKey, where: a.is_active == true)

Но, к сожалению, как я вижу, метод предварительной загрузки не может изменить набор api_keys, когда данные уже предварительно загружены.

Не могли бы вы показать мне хороший пример - как предварительно загрузить только "активные" api_keys?


person Alexey Poimtsev    schedule 03.01.2016    source источник


Ответы (1)


Эта проблема на Ecto может быть актуальна для вас.

В настоящее время у вас есть два варианта:

Используйте Enum.map после получения с помощью join и select:

query = from u in User, 
        join: a in assoc(u, :api_keys), 
        where: u.email == ^email,
        where: a.is_active == true,
        select: {u, a}
user = Repo.one(query) |> Enum.map(fn ({u, a}) -> %{u | api_keys: a} end)

Используйте запрос в качестве аргумента для Ecto.Query.preload/3:

api_key_query = from a in ApiKey, where: a.is_active == true
query = from u in User, 
        join: a in assoc(u, :api_keys), 
        where: u.email == ^email,
        preload: [api_keys: ^api_key_query]
user = Repo.one(query)
person Gazler    schedule 03.01.2016
comment
во втором варианте вы написали, что приложение будет выполнять 2 запроса БД вместо одного :( - person Alexey Poimtsev; 04.01.2016
comment
@AlexeyPoimtsev Выполнение двух или более запросов всегда имеет место при использовании предварительной загрузки. Однако предварительная загрузка часто может работать лучше, чем использование соединений. Прочтите раздел «Запросы ассоциаций» в блоге . plataformatec.com.br/2015/08/ — часто это самый эффективный способ загрузки ассоциаций из базы данных (даже если выполняется два запроса), потому что нам нужно получать и анализировать только результаты POSTS + COMMENTS. - person Gazler; 04.01.2016
comment
@Gazler, можно ли дважды вступить в одну и ту же ассоциацию в Ecto, каждый раз с разными условиями? Я получаю сообщение об ошибке cannot preload prices`, так как оно было предоставлено более одного раза с разными запросами`, поэтому я предполагаю, что это нет. Но как это обойти? - person Mohamad; 04.06.2017