我正在寻找一种更好的方法,如果可能的话,使用惊人的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.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 >
但我想知道,如果有更好,更智能,更快捷,更有效,更有效,美学(或只是“不同”)的方式,那么这样做......
答案 0 :(得分: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:可能你不想在map
上使用User.all
,如果你有很多繁重的用户文档,它将需要大量的内存。此外,您没有使用映射的用户,而是自己在competitors
数组中收集结果,因此each
应该可以正常工作。