2

我有两个模型,它们之间的关联是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: 错误: 关系 "tasks" 的列 "user_group_ids" 不存在

生成的查询:

SQL (0.6ms) UPDATE "tasks" SET "user_group_ids" = 4, "release_date" = '2017-04-27 07:40:26.525357' 其中 "tasks"."deleted_at" 为 NULL AND "tasks"."id" = 47394

请让我知道怎么做update_all

4

3 回答 3

0

您不能使用update_all. update_all执行单个 UPDATE 查询,但对于关联,您实际上需要一个 INSERT 查询来插入关联的模型。您可以使用 gem 像bulk_insert通过一个 INSERT 查询来插入所有连接对象https://github.com/jamis/bulk_insert

于 2019-06-13T15:16:39.317 回答
0

为什么必须创建 UserGroup 模型?这不是我们使用habtm关系的方式。

而你的模型Task,在这一切的中间,让我有点困惑。你需要做什么?我怀疑你habtmTask.

对于您遇到的错误,这是完全可以理解的。您没有user_group_idstasks表中调用的属性(列)。而且,对于一段habtm关系,这个属性user_group_ids对我来说似乎拼错了。

无论如何,对于一个habtm关系,如果您的用户有很多组并且一个组可以有很多用户,那么您就走在了正确的道路上,但是对于 Ruby on Rails,您可以通过两种方式来实现这一点。

  1. 如果不需要管理关系表中的其他数据(关系属性):

    • 那么你只需要 table groups_users,在你的情况下。Rails 将按habtm字母顺序查找关系表。
  2. 如果您的groups_users关系包含模型的参考 ID 以外的任何其他数据,那么您最好使用has_many :through关系。

    • 在这种情况下,您的 UserGroup(请注意奇点)表将包含您在关系中需要的其他数据。然后你声明如下:

    • User模型将声明:has_many :groups, through: :user_groups

    • Group模型将声明:has_many :users, through: :user_groups
    • UserGroup型号:belongs_to :userbelongs_to :group。注意不要将其中任何一个索引为唯一的、数据库或应用程序级别。

有关更多详细信息,请查看http://guides.rubyonrails.org/association_basics.html#the-has-and-belongs-to-many-association

希望你得到你的结果!

于 2017-04-27T09:58:14.873 回答
0

您的解决方案(不会导致 N+1)是activerecord-import

于 2019-06-12T18:16:55.917 回答