我有两个模型,它们之间的关联是has_and_belongs_to_many
。
我需要重构代码,因为它会导致n + 1个查询。
问题:n + 1次查询
1。任务
class Task < ActiveRecord::Base
has_and_belongs_to_many :user_groups
end
2。用户组
class UserGroup < ActiveRecord::Base
has_and_belongs_to_many :tasks
end
要求:
将任务分配给user_groups
以前的控制器代码:
task_ids.each do |task_id|
find(task_id).update_attributes! user_group_ids: params[:user_group_ids], release_date: params[:release_date]
end
我的尝试:
tasks = Task.where(id: task_ids)
tasks.update_all(user_group_ids: params[:user_group_ids], release_date: params[:release_date])
错误:
ActiveRecord :: StatementInvalid(PG :: UndefinedColumn:ERROR:column 关系“任务”的“user_group_ids”不存在
查询已生成:
SQL(0.6ms)UPDATE“tasks”SET“user_group_ids”= 4, “release_date”='2017-04-27 07:40:26.525357'WHERE“tasks”。“deleted_at”IS NULL和“tasks”。“id”= 47394
请通过update_all
答案 0 :(得分:0)
为什么必须创建UserGroup模型?这不是我们使用habtm
关系的方式。
你的模型Task
,在这一切的中间,有点困惑我。你需要做什么?我怀疑您在habtm
中没有Task
关系。
对于你得到的错误,这完全可以理解。您在user_group_ids
表中没有名为tasks
的属性(列)。此外,对于habtm
关系,此属性user_group_ids
似乎拼写错误。
无论如何,对于habtm
关系,如果你的用户有很多组,而一个组可以拥有很多用户,那么你就是正确的道路,但是对于Ruby on Rails,有两种方法可以实现这一点。 / p>
如果您不需要管理关系表中的其他数据(关系属性):
groups_users
。 Rails将按字母顺序查找habtm
关系表。如果您的groups_users
关系包含除模型参考ID之外的任何其他数据,那么您最好使用has_many :through
关系。
在这种情况下,您的UserGroup(介意奇点)表将保存关系中所需的其他数据。然后你声明如下:
User
模型已声明:has_many :groups, through: :user_groups
Group
模型已声明:has_many :users, through: :user_groups
UserGroup
型号:belongs_to :user
和belongs_to :group
。注意不要将其中任何一个索引为唯一,数据库或应用程序级别。有关详细信息,请查看http://guides.rubyonrails.org/association_basics.html#the-has-and-belongs-to-many-association
希望你得到你的结果!
答案 1 :(得分:0)
您的解决方案(不引起N + 1)是activerecord-import
答案 2 :(得分:0)
您无法使用update_all
大规模分配关联。 update_all
仅执行一个UPDATE查询,但实际上,要进行关联,您需要一个INSERT查询来插入关联的模型。您可以使用bulk_insert
之类的gem通过一个INSERT查询https://github.com/jamis/bulk_insert