Rails ActiveRecord Access (дочерние объекты?) Последних созданных объектов - PullRequest
0 голосов
/ 11 октября 2019

как сказал заголовок, я пытаюсь получить доступ к массиву объектов ассоциации Это ассоциация has_many

вот мой класс

class Keyword < ApplicationRecord
   has_many :rankings
end


class Ranking < ApplicationRercord
    belongs_to :keyword
end

В рейтинге есть атрибут, называемый позицией: integer, я хочу иметь возможность получить доступ ко всем последним созданным рейтингам по всем ключевым словам. Вот что я получил до сих пор

Keyword.all.joins(:rankings).select( 'MAX(rankings.id) ').pluck(:created_at, :keyword_id, :position)

Я прочитал еще один пост, предлагающий использовать MAX на Rankings.id,но я все еще не могу вернуть массив

В данный момент возвращение Keyword.count 4597 Возвращение Ranking.count 9245

Каждое ключевое слово сгенерировало около 2 ранжирований, но я просто хочу последний рейтингот каждого ключевого слова в формате массива, поэтому для получения последнего из каждого я должен ожидать около 4597

Не уверен, если я объяснил достаточно ясно, надеюсь, вы, ребята, можете мне помочь: '(спасибо, действительно ценю это

Ответы [ 3 ]

1 голос
/ 13 октября 2019

Если вы используете Postgres . Вы можете использовать DISTINCT ON

Keyword.joins(:rankings)
       .select("DISTINCT ON(ratings.keyword_id) keywords.*, ratings.position, ratings.created_at AS rating_created_at")
       .order("ratings.keyword_id, ratings.id DESC") 

Теперь вы можете получить доступ position, rating_created_at

@keywords.each do |k|
  k.position
  ....

@keywords.map { |k| [k.id, k.rating_created_at, k.position] }
0 голосов
/ 12 октября 2019

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

class Keyword < ApplicationRecord
   belongs_to :latest_ranking, class_name: :ranking
   has_many :rankings, after_add: :set_latest_ranking

   def set_latest_ranking(ranking)
     self.update!(latest_ranking: ranking)
   end
end

Keyword.joins(:latest_ranking)
       .pluck(:created_at, :id, "rankings.position")

Это позволяет легко присоединиться и получить высокую производительность. Я узнал об этом после работы с приложением, которое имело огромное количество строк, и попробовал каждое возможное решение, такое как боковые объединения, чтобы улучшить довольно удручающую производительность запроса.

Стоимость создания дополнительного запроса записи при создании записи.

0 голосов
/ 11 октября 2019
Keyword.joins(:rankings).group("keywords.id").pluck("keywords.id", "MAX(rankings.id)")

Это даст вам массив, элементы которого будут содержать идентификатор keyword и идентификатор самого последнего ranking, связанный с этим keyword.

Если вам нужнополучить больше информации о rankings, а не id, вы можете сделать это так:

last_rankings_ids_scope = Ranking.joins(:keyword).group("keywords.id").select("MAX(rankings.id)")

Ranking.where(id: last_rankings_ids_scope).pluck(:created_at, :keyword_id, :position)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...