N+1 查询是大家经常碰到要去消灭的东西。常用的方法就是使用 #includes/joins/eager_load 等方法,在查询数据集的时候通知 ORM 去将关联数据用某种方式先预载出来. 但是开发时老要想着这件事还是比较烦人的。最近在用 GraphQL 重写一个后台服务碰到比较头疼的问题。在写 API 的时候,每个接口返回的数据都是非常确定的,所以可以事先确定什么地方需要进行 eager loading. GraphQL 将组织查询结果的权利交给了前端。这时候后端就无法在编写代码时就确定要 eager load 哪些关系了. 在 ActiveRecord 的世界中有一个很出色的 gem Goldiloader. 可以在代码执行中根据对关系的访问来自动执行 eager_load. 找了很久,在 Mongoid 社区似乎还没有一个这样的 gem. 于是只能自己去实现类似的功能。
自动 依据对关系的访问,决定是否进行 eager loading:
新增两个选项 :auto_include
和 :fully_load
.
class User
include Mongoid::Document
belongs_to :user_groups, auto_include: false
has_many :posts, fully_load: true
end
在 Gemfile 中添加
gem 'mongoload'
或是通过 gem 命令安装
gem install mongoload