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

时间:2012-04-12 10:42:42

标签: ruby-on-rails ruby mongodb mongoid database

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

假设您有一个embedded one to many数据模型,如下所示:

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. 关注列表的html_url内容
  2. 关注列表的描述内容
    1. 相关的父昵称(User.nickname)
    2. 我试过这样的事情:

      1.9.2p290 :574 > Competitor = Struct.new(:html_url, :description, :user)
      => #<Class:0xed08de8>
      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 << Competitor.new(wl.html_url, wl.description, wl.user.nickname)
      1.9.2p290 :580?>           end
      1.9.2p290 :581?>     end
      1.9.2p290 :582?> end
      

      这里有一些改动:

      1.9.2p290 :585 > competitors
      => [#<struct html_url="https://github.com/rails/rails", description="Ruby on Rails", user="lgs">, #<struct html_url="https://github.com/sinatra/sinatra", description="Classy web-development dressed in a DSL (official / canonical repo)", user="lgs">]
      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 >
      

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

1 个答案:

答案 0 :(得分:2)

你做了两件事:

  • 使用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:可能你不想在map上使用User.all,如果你有很多繁重的用户文档,它将需要大量的内存。此外,您没有使用映射的用户,而是自己在competitors数组中收集结果,因此each应该可以正常工作。