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

У меня есть объект с именем " Факт ", этот объект связан с другим объектом с именем " Пользователь ", это отношение называется " Обратная связь ", что имеет 3 поля [user_id, fact_id, Score] каждый раз, когда человек дает отзыв, который он получал ( user_id ) на какой факт был сделан ( fact_id ) и что было квалифицировано ( 0,1,2 ). Что ж, теперь я хочу получить список фактов с их квалификацией, например:

fact : {id: 3, name: "some name", number_of_zero: 7, number_of_one: 3, number_of_two: 3}

где number_of - количество раз, которое оно было квалифицировано.

Схема базы данных:

  create_table "facts", force: :cascade do |t|
    t.string "title"
    t.string "description"
    t.integer "user_id"
  end

  create_table "users", force: :cascade do |t|
    t.string "name"
    t.string "last_name"
  end

create_table "feedbacks", force: :cascade do |t|
    t.integer "score"
    t.integer "user_id"
    t.integer "fact_id"
    t.index ["fact_id"], name: "index_feedbacks_on_fact_id"
    t.index ["user_id"], name: "index_feedbacks_on_user_id"
  end

Отношения:

class Feedback < ApplicationRecord
  belongs_to :user
  belongs_to :fact
end

Ответы [ 3 ]

0 голосов
/ 09 сентября 2018
Fact.
  group(:id, :name).
  select(:id, name).
  left_joins(:feedbacks).
  select("COUNT(feedbacks.id) FILTER (WHERE score = 0) AS number_of_zero").
  select("COUNT(feedbacks.id) FILTER (WHERE score = 1) AS number_of_one").
  select("COUNT(feedbacks.id) FILTER (WHERE score = 2) AS number_of_two")

Вам необходимо left_joins, чтобы также возвращались факты с обратной связью 0 (с 0 для каждого столбца подсчета).

Как сказал Рохан, вам нужно добавить has_many :feedbacks в fact.rb

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

Редактировать: Для SQLite (я думаю, что он поддерживает коррелированные подзапросы ...)

Fact.
  select(:id, name).
  select("(SELECT COUNT(*) FROM feedbacks WHERE score = 0 AND fact_id = facts.id) AS number_of_zero").
  select("(SELECT COUNT(*) FROM feedbacks WHERE score = 1 AND fact_id = facts.id) AS number_of_one").
  select("(SELECT COUNT(*) FROM feedbacks WHERE score = 2 AND fact_id = facts.id) AS number_of_two")
0 голосов
/ 09 сентября 2018
Model:
class Feedback < ApplicationRecord
  belongs_to :user
  belongs_to :fact
end
class Fact < ApplicationRecord
 has_many :feedbacks
end
 fact = Fact.all
  array = []
 fact.each do |each_fact|
    arr = {}
    each_fact.feedbacks do |each_feedback|
       arr["id"] = each_feed_back.id
       arr["name"] = each_feedback.name
       arr["no_of_zero"] = each_feedback.score 
       array << arr
   end
end
0 голосов
/ 08 сентября 2018

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

Что-то, что упомянуто ниже, может помочь вам достичь:

Fact.joins(:feedbacks).select("facts.id, facts.title,CASE when feedbacks.score is 0 
then count(feedbacks.score) as score_0 end,
CASE when feedbacks.score is 1 then count(feedbacks.score) as score_1 end,
CASE when feedbacks.score is 2 then count(feedbacks.score) as score_2 end")
.group("feedbacks.score")

Вышеупомянутый запрос объединяет отзывы с фактом, а затем группирует значения баллов, поскольку будет только три значения, то есть 0,1,2 (как упомянуто в посте).

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