1

如果可能的话,我正在寻找一种更好的方法来使用令人惊叹的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. 关注列表的 html_url 内容
  2. 关注列表的描述内容

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

我试过这样的事情:

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 >

但我想知道,是否有更好、更智能、更快、高效、有效、美观(或只是“不同”)的方式来做到这一点......

4

1 回答 1

2

你做两件事:

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

于 2012-04-12T12:04:32.617 回答