N + 1查询检测到这意味着我该怎么做才能使其正常工作。
我使用Bullet gem来显示N + 1个查询
user: kalyan
N+1 Query detected
Emp => [:functions]
Add to your finder: :include => [:functions]
N+1 Query method call stack
/home/Documents/app/views/tics/show.html.haml:20:in `_app_views_tics_show_html_haml___2301551533476719406_237290860'
这是来自bullet gem的消息。
_app_views_tics_show.html.haml
- if (@tic.assigned_to == current_user.emp) or (current_user.emp_functions.map{|x| x.id}.include?(1) if current_user.emp_functions.present? )
= best_in_place @tic, :subject
- else
= @tic.subject
帮我减少n + 1查询问题
emp.rb
has_many :emp_functions, inverse_of: :emp,dependent: :restrict_with_exception
belongs_to:user,inverse_of :: emp
emp_functions.rb
belongs_to :emp , inverse_of: :emp_functions
belongs_to :function
function.rb
has_many :emp_functions, dependent: :restrict_with_exception
has_many :emp, through: :emp_functions
user.rb
has_one :emp, inverse_of: :user, dependent: :restrict_with_exception
答案 0 :(得分:1)
Imho,摆脱这个N + 1查询的最有效方法是改变current_user
方法,将includes(:emp_functions)
添加到User.find
调用。您的方式取决于您处理身份验证的方式。如果您正在使用某种类型的gem(例如Devise
或Sorcery
),则需要重新打开这些类并更改方法,而不是忘记使用super
。如果你自己编写了自己的身份验证,那么你就可以更容易地做到这一点。
我注意到的第二件事是,您实际上不需要在视图中的map
上使用user.emp_functions
,前提是emp_functions
是has_many
关联的User
current_user.emp_function_ids.include?(1)
模型。您可以将其展平为emp_functions
。这将帮助您摆脱N + 1查询问题,但仅限于此特定情况。如果您经常在很多地方处理当前用户的{{1}},我建议使用我描述的第一条路径。
第三件事,与问题没有直接关系的是我真的不认为代码属于视图。您应该将其移动到帮助器或装饰器,使视图保持清洁和可读。
答案 1 :(得分:0)
如果emp_functions
是您用户模型上的has_many关联(似乎是这样),那么您应该这样做:
current_user.emp_function_ids.include?(1)
答案 2 :(得分:0)
这是针对您的问题的一个非常具体的解决方案,我建议不要在视图中使用它
将current_user.emp_functions.map{|x| x.id}.include?(1)
更改为
current_user.emp_functions.where(id: 1).exists?
每当您点击包含它的页面时,这将导致对数据库进行1次单一查询。
您还可以删除if
语句以删除另一个数据库查询。