В отношении 1-ко-многим Rails ActiveRecord, как лучше всего получать родительские записи, которые имеют только дочерние записи? - PullRequest
1 голос
/ 14 января 2020

У меня есть Post модель, в которой много comments

class Post < ApplicationRecord
  has_many :comments
end

Как получить отдельные сообщения с комментариями, исключая сообщения без комментариев?

I считаю, что Post.joins(:comments).distinct("posts.*") делает свою работу.

Есть ли лучшая альтернатива?

Я подчеркиваю, что в результате не должно быть дубликатов записей, что и происходит, когда мы присоединяемся с комментариями (отношение один ко многим).

Ответы [ 4 ]

3 голосов
/ 14 января 2020

Снова посмотрев на это, и учитывая комментарии Марка к моему исходному решению, самое простое решение - просто удалить "posts.*" из вашего оригинала.

Post.joins(:comments).distinct
1 голос
/ 14 января 2020

На самом деле вам не нужно действительно использовать distinct в конце, это совсем не эффективно, так как вы выбираете все по умолчанию (posts.*), которое имеет уникальный первичный ключ (id) для каждой записи.

Post.joins(:comments)
# SELECT `posts`.* FROM `posts` INNER JOIN `comments` ON `comments`.`post_id` = `posts`.`id`

Примечание:

Чтобы самим увидеть разницу, попробуйте выполнить следующие запросы.

Post.joins(:comments).count
Post.joins(:comments).distinct.count

# Both should be giving you the same numbers.
1 голос
/ 14 января 2020

Это работает, хотя, очевидно, дело вкуса в том, что лучше:

Post.left_outer_joins(:comments).where.not(comments: {id: nil})

И left_outer_joins пришли с Rails 5, поэтому в более ранних версиях требуется более подробное решение. См. Поиск ноль ассоциаций has_one, в которых запрос

Самое приятное в этом - он прекрасно сочетается с противоположным запросом:

Post.left_outer_joins(:comments).where(comments: {id: nil})

Что все сообщения без комментарии

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

Этого также можно добиться с помощью подзапроса:

Post.where(id: Comment.select(:post_id).distinct)

Время загрузки зависит от количества комментариев в базе данных.

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