【发布时间】:2014-12-26 13:51:35
【问题描述】:
我的项目中有 3 个模型:Users、Games、GameVisits
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
我的前端是用 angularjs 编写的,所以我想要一个函数,它可以为游戏列表返回散列数组,每个散列包含用户名和状态或 nil。数据显示为表格,列 - 玩家,行 - 游戏,单元格 - 玩家在游戏中的存在。 这是此类功能的示例:
def team_json(game_ids = nil)
game_ids ||= Game.pluck(:id)
games = Game.find(game_ids)
users = self.users
result = []
games.each do |game|
record = {name: game.name, date: game.date }
users_array = []
users.each do |user|
users_array << {
name: user.name,
status: user.game_visits.find_by_game_id(game.id)
}
end
record[:users] = users_array
result << record
end
result
end
输出:
[{:name=>"game 0", :date=>2014 年 12 月 19 日星期五 11:16:20 UTC +00:00, :users=>[{:name=>"Bob", :status =>无}]}, {:name=>"game 1", :date=>Sat, 2014 年 12 月 20 日 11:16:20 UTC +00:00, :users=>[{:name=>"Bob", :status=>nil} ]}, {:name=>"game 2", :date=>Fri, 19 Dec 2014 11:16:20 UTC +00:00, :users=>[{:name=>"Bob", :status=>nil} ]}]
但是这个函数会为 GameVisits 生成大量的 sql 查询:
(1.0ms) SELECT "games"."id" FROM "games"
Game Load (1.3ms) SELECT "games".* FROM "games" WHERE "games"."id" IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101)
User Load (0.6ms) SELECT "users".* FROM "users" WHERE "users"."team_id" = $1 [["team_id", 1]]
GameVisit Load (0.6ms) SELECT "users_games".* FROM "users_games" WHERE "users_games"."user_id" = $1 AND "users_games"."game_id" = $2 LIMIT 1 [["user_id", 7], ["game_id", 1]]
GameVisit Load (0.6ms) SELECT "users_games".* FROM "users_games" WHERE "users_games"."user_id" = $1 AND "users_games"."game_id" = $2 LIMIT 1 [["user_id", 7], ["game_id", 2]]
GameVisit Load (0.5ms) SELECT "users_games".* FROM "users_games" WHERE "users_games"."user_id" = $1 AND "users_games"."game_id" = $2 LIMIT 1 [["user_id", 7], ["game_id", 3]]
..............
如何优化它?
【问题讨论】:
标签: sql ruby-on-rails json angularjs has-and-belongs-to-many