Gem Mongoid 的自动 eager load: Mongoload

karloku · 2016年04月27日 · 最后由 karloku 回复于 2016年04月28日 · 2382 次阅读

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

功能

自动 依据对关系的访问, 决定是否进行 eager loading:

  • has_one
  • has_many
  • belongs_to
  • has_and_belongs_to_many

2016-4-28 更新

新增两个选项 :auto_include:fully_load.

class User
  include Mongoid::Document
  belongs_to :user_groups, auto_include: false
  has_many :posts, fully_load: true
end
  • auto_include: true/false. 当值为 false 时, 不自动进行 eager loading
  • fully_load: true/false. 当值为 true 时, 执行 #first, #last, #size, #empty? 等方法, 也会先进行 eager loading.

安装

在 Gemfile 中添加

gem 'mongoload'

或是通过 gem 命令安装

gem install mongoload

支持版本

  • ruby >~ 2.1 (用到 Module#prepend)
  • mongoid >~ 5.0 另外支持 github.com/mongodb/mongoid/tree/master 分支中的 mongoid 6.0.0, 由于 mongoid 6.0.0 依赖 ActiveModel 5.0.0, 因此需要 ruby >= 2.2.2

Github

Mongoload

请问 用了 mongo 还会有 N+1 问题出现吗?

#1 楼 @pathbox 有时候建模还是免不了用 reference 关系的.

好吧。。。越来越觉得 pg 是个好选择

本来 Mongoid 就有 includes 功能做类似的事情啊!

哦,自动的!

#4 楼 @huacnlee 恩, 根据对关系的访问自动决定什么时候该进行 eager loading.

Update: 新增两个控制选项

需要 登录 后方可回复, 如果你还没有账号请 注册新账号