使用mongoid / mongodb提取,建模和更改数据模型

我正在寻找一种更好的方法,如果可能的话,使用惊人的mongoid ODM驱动程序来操纵现有的mondodb数据模型。

假设您有一个嵌入的一对多数据模型,如下所示:

class User include Mongoid::Document field :nickname embeds_many :watchlists end class Watchlist include Mongoid::Document field :html_url field :description field :tags_array, type: Array embedded_in :user end 

现在,对于所有用户,您只想提取每个监视列表的一部分,当且仅当它具有

 tags_array == ["ruby", "web", "framework"] 

只返回几个字段(不是整个监视列表文档):

  1. watchlist的html_url内容
  2. 关注列表的描述内容

  1. 相关父昵称(User.nickname)

我试过这样的事情:

 1.9.2p290 :574 > Competitor = Struct.new(:html_url, :description, :user) => # 1.9.2p290 :575 > competitors = [] => [] 1.9.2p290 :576 > User.all.map do |user| 1.9.2p290 :577 > user.watchlists.all.map do |wl| 1.9.2p290 :578 > if wl.tags_array == ["ruby", "web", "framework"] 1.9.2p290 :579?> competitors < end 1.9.2p290 :581?> end 1.9.2p290 :582?> end 

这里有一些结果:

 1.9.2p290 :585 > competitors => [#, #] 1.9.2p290 :586 > competitors.size => 2 1.9.2p290 :599 > competitors[0][:html_url] => "https://github.com/rails/rails" 1.9.2p290 :600 > competitors[1][:html_url] => "https://github.com/sinatra/sinatra" 1.9.2p290 :601 > 

但我想知道,如果有更好,更智能,更快捷,更有效,更美观(或只是“不同” )的方式,那么这样做……

你做两件事:

  • 使用db查询过滤用户而不是在应用程序中过滤
  • 只从db获取你需要的字段,而不是整个用户对象(假设你在用户中有一些其他的东西,为简洁你省略了这些东西)

     Competitor = Struct.new(:html_url, :description, :user) competitors = [] User.where('watchlists.tags_array' => %w[ruby web framework]). only(:nickname, :watchlists).each do |u| u.watchlists.where(:tags_array => %w[ruby web framework]).each do |wl| competitors << Competitor.new(wl.html_url, wl.description, u.nickname) end end 

PS:可能你不想在User.all上使用map ,如果你有很多繁重的用户文档,它将需要大量的内存。 此外,您没有使用映射的用户,而是自己在competitorsarrays中收集结果,因此each应该正常工作。