1

可能であれば、素晴らしいmongoid ODMドライバーを使用して既存の mondodb データモデルを操作するためのより良い方法を探しています。

次のような 1 対多のデー​​タ モデルが埋め込まれているとします。

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

次の 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
    

mapPS: おそらく、 onを使用したくないでしょうUser.all。大量のユーザー ドキュメントがある場合は、大量のメモリが必要になります。また、マップされたユーザーを使用していませんが、代わりにcompetitors自分で配列に結果を収集しているため、each問題なく動作するはずです。

于 2012-04-12T12:04:32.617 に答える