Sql 查询多对多关联

Sql 查询多对多关联,sql,ruby-on-rails,json,angularjs,has-and-belongs-to-many,Sql,Ruby On Rails,Json,Angularjs,Has And Belongs To Many,我的项目中有3个模型:用户、游戏、游戏访问 class User < ActiveRecord::Base has_many :game_visits has_many :games, through: :game_visits end class Game < ActiveRecord::Base has_many :game_visits has_many :users, through: :game_visits end class GameVisit &l

我的项目中有3个模型:用户、游戏、游戏访问

class User < ActiveRecord::Base
  has_many :game_visits
  has_many :games, through: :game_visits
end

class Game < ActiveRecord::Base
  has_many :game_visits
  has_many :users, through: :game_visits
end

class GameVisit < ActiveRecord::Base
  self.table_name = :users_games
  enum status: [:visited, :not_visited, :unknown]
  belongs_to :user
  belongs_to :game
end

如何优化它?

您的
用户。game\u访问。按game\u id(game.id)
查找是触发所有这些查询的原因。您可以使用快速加载来解决此问题

用户的分配更改为以下内容:

users = self.users.includes(:game_visits)
然后将
users\u array
中的
status
的赋值更改为:

status: user.game_visits.find{ |gv| gv.game_id == game.id }
上面的行使用的是可枚举的
find
,而不是ActiveRelation。如果您坚持使用AR的
find\u by\u game\u id
或其他
find
,它仍然会触发查询

另一个优化方法是为
游戏访问创建一个哈希,这样您就可以到处
查找
来执行如下操作:

user_game_visits_hash = \
  user.game_visits.each_with_object({}) do |gv, hash|
    hash[gv.game_id] = gv
  end

# more code here

status: user_game_visits_hash[game.id]
还有一个小问题:如果方法参数中的
game\u id
为零,那么方法的前两行将不必要地触发两个查询,因为您从游戏中提取所有id只是为了获取所有游戏。您可以将其更改为:

games = game_ids ? Game.find(game_ids) : Game.all
user_game_visits_hash = \
  user.game_visits.each_with_object({}) do |gv, hash|
    hash[gv.game_id] = gv
  end

# more code here

status: user_game_visits_hash[game.id]
games = game_ids ? Game.find(game_ids) : Game.all