Rails: как загрузить ассоциации в одном запросе при настройке столбцов ассоциации - PullRequest
0 голосов
/ 22 января 2020

Если я использую eager_load для извлечения нужной ассоциации в одном запросе, я получаю слишком много столбцов:

scope = Product.eager_load(:account).to_a
scope.last.account.name

Затем я получаю запрос, который выглядит следующим образом:

 SQL (3.3ms)  SELECT "products"."id" AS t0_r0, "products"."account_id" AS t0_r1, "products"."notes" AS t0_r2, "products"."created_at" AS t0_r3, "products"."updated_at" AS t0_r4, "products"."rep_id" AS t0_r5, "products"."senior_rep_id" AS t0_r6, "products"."name_id" AS t0_r7...

Моя цель - просто получить нужные столбцы, как я ожидал, позвонив по номеру .select("intakes.id, intakes.account_id, accounts.id, accounts.name"). Однако, если я добавлю это к моему запросу, он просто добавляет эту строку вперед и в основном игнорирует ее:

 SQL (3.3ms)  SELECT products.id, products.account_id, accounts.id, accounts.name, "products"."id" AS t0_r0, "products"."account_id" AS t0_r1, "products"."notes" AS t0_r2, "products"."created_at" AS t0_r3, "products"."updated_at" AS t0_r4, "products"."rep_id" AS t0_r5, "products"."senior_rep_id" AS t0_r6, "products"."name_id" AS t0_r7...

Так что теперь мой запрос стал еще длиннее, но я не получил никакой выгоды. Я также могу попробовать с left_joins:

scope = Product.left_joins(:account).select("products.id, products.account_id, accounts.id, accounts.name").to_a

Это даст мне N + 1 запросов, где выбор игнорируется для ассоциаций:

Products Load (0.9ms)  SELECT products.id, products.account_id, accounts.id, accounts.name FROM "products" LEFT OUTER JOIN "accounts" ON "accounts"."id" = "products"."account_id"
Account Load (0.2ms)  SELECT "accounts".* FROM "accounts" WHERE "accounts"."id" = $1 LIMIT $2  [["id", 16], ["LIMIT", 1]]

Однако я могу избежать N +1, если я узнаю выбранные столбцы DID go где-нибудь, в этом accounts.name, сопоставленном с name в Продукте:

scope.last.attributes["name"]

Технически это дает мне информацию, которую я хочу получить в одном запросе, но при создании реального запроса со многими ассоциациями попытка переименовать и переназначить эти данные во множество пользовательских имен внезапно заставляет задуматься, почему я вообще использую ActiveModel. Есть ли еще «Rails Way» для этого, где scope.last.account.name будет по-прежнему иметь значение, установленное так, как если бы я использовал eager_load?

1 Ответ

0 голосов
/ 23 января 2020

Вы можете оставить запрос scope = Product.left_joins(:account).select("products.id, products.account_id, accounts.id, accounts.name").to_a, чем ваша вторая строка должна быть похожа на scope.last.name, чтобы предотвратить второй запрос БД. Если у вас есть одинаковые столбцы в таблицах счетов и продуктов, задайте для них разные имена в методе выбора (например, scope = Product.left_joins(:account).select("products.id, products.account_id, accounts.id, accounts.name as account_name").to_a, чем извлекайте его как scope.last.account_name.

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