MongoDB Mongoid 怎样做关联查询?

bindiry · 发布于 2012年02月09日 · 最后由 lukefan 回复于 2013年05月17日 · 6026 次阅读

例如我有两张表:

  • brands和devices
  • brand has_many devices
  • devices belongs_to brand

我想在一个页面列出所有brands,以及每个brand下面的devices。

我现在的做法是先 @brands = Brand.all,然后通过循环取每个brand下面的devices,就像下面这样:

@brands.each do |brand|
  brand.devices.each do |device|
    do something...
  end
end

但是看日志,每次brand.devices.each 都会再去查询一次。

想请教一下,怎样做到关联查询,一次性把brands及下面的devices一起按结构层级取出来?

共收到 25 条回复
@brands = Brand.includes(:devices)

这样就可以了。

学习!

我才发现 mongoid 有 Eager load

#1楼 @huacnlee 谢谢华顺指教。

@huacnlee 刚才试了一下@brands = Brand.includes(:devices),发现控制台输入的查询似乎是对的:

MONGODB demo_development['brands'].find({}).sort([[:name, :asc]])
MONGODB demo_development['devices'].find({"brand_id"=>{"$in"=>[BSON::ObjectId('4f03391e11aa2b1401000001'), BSON::ObjectId('4f03391e11aa2b1401000004'), BSON::ObjectId('4f03391e11aa2b1401000008'), BSON::ObjectId('4f03391e11aa2b1401000006')]}}).sort([["name", :asc]])

但是到我循环显示brand.devices.each的时候,还是会再去查询devices:

MONGODB demo_development['brands'].find({}).sort([[:name, :asc]])
MONGODB demo_development['devices'].find({"brand_id"=>BSON::ObjectId('4f03391e11aa2b1401000001')}).sort([["name", :asc]])
MONGODB demo_development['devices'].find({"brand_id"=>BSON::ObjectId('4f03391e11aa2b1401000004')}).sort([["name", :asc]])
MONGODB demo_development['devices'].find({"brand_id"=>BSON::ObjectId('4f03391e11aa2b1401000008')}).sort([["name", :asc]])
MONGODB demo_development['devices'].find({"brand_id"=>BSON::ObjectId('4f03391e11aa2b1401000006')}).sort([["name", :asc]])

然后我用rails console,输入Brand.includes(:devices).to_a,显示的也只有brands这一级内容,devices没有显示。

是我哪里没搞正确吗?

#5楼 @bindiry 官网上有写:

In order for #includes to work the Mongoid identity map must be enabled in the mongoid.yml:
identity_map_enabled: true

你看看是不是忘记设置这个

#6楼 @HungYuHei 这个设置试过,没起作用。

哦,我搞错了,这个 has_many 的好像无法 includes 的 Mongoid 官方都有这种用法,不过现在 Ruby China 的“酷站”里面都不行 http://mongoid.org/docs/querying/criteria.html#includes

我再查查看

#9楼 @huacnlee 谢谢,看官方文档有这么一句:This only works with has_many, has_one, and belongs_to relations and only 1 level deep at the current moment.

#10楼 @bindiry

Person.includes(:posts, :game)

#11楼 @huacnlee 那看起来会不会是个bug?

@huacnlee @HungYuHei

问题解决了,我犯了个低级错误,把identity_map_enabled: true加到development:外面去了。。。 加到development:里就正常了。。。 掩面奔逃。。。

好吧,我是来围观的...

我搞了个many_to_many的,看来是没戏了。

#7楼 @bindiry #11楼 @huacnlee 如此例,如果需要用 brand 的 field 作为where里面的查询条件,来查询 devices 数据。怎么办呢?

#16楼 @suxu 围观 学习了!如果我用devices的created_at 来排序!我该如何做?

18楼 已删除

#17楼 @tanjianna

查询 devices 数据。还是brands 数据?

#19楼 @suxu 查询devices数据

#20楼 @tanjianna brand has_many devices

可以直接 ,brand.devices 啊。如果需要查询条件,跟上 where 即可

#15楼 @lukefan 我也在找

#22楼 @lxyluu has_and_belongs_to_many :tags, inverse_of: nil doc 和 tag之间,就是多对多的。 @articles = Article.desc(:updated_at).where(:tag_ids.in => [params[:tag_id]]) 这样查询。

@lukefan 多对多下,如果params[:tag_id]是一个id数组呢?就是[1,2,3]查询出同时有这个的article!

#24楼 @stephen 我没有做多标签选择,不过,搜集多个id应该是没有问题的吧。

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