2

私はClientGroupモデルを持っています。クライアントには多くのグループがあります。

class Client
  include Mongoid::Document
  include Mongoid::Paranoia
  include Mongoid::Timestamps

  field ...

  has_many :groups, dependent: :delete

  ...
end

class Group
  ...

  belongs_to :client
end

1 つのクライアントに40,000のグループがあり、試しclient.groupsてみると時間がかかりすぎます。数分待っても終わりません。

MONGODB (14.2ms) humtl_development['groups'].find({:deleted_at=>nil, "client_id"=>BSON::ObjectId('51b37763218c5a19e0000048')})
MONGODB [DEBUG] cursor.refresh() for cursor 48594378191047181

私はモンゴイドのドキュメントでこれを見つけました。

40k はドキュメントが多すぎますか? has_many関係を取り除き、embeds_many代わりに使用する必要がありますか? 問題は私のmongoidバージョンですか?MongoDB 構成? アドバイスをいただければ幸いです。

確かに、40,000 個のグループすべてを表示する必要はありません。必要なのはUser.where(:group_id.in => client.groups.map(&:id)).

本当にありがとう。

PS: MongoDB v2.4.3 mongoid v2.7.1 mongo v1.9.2

4

1 に答える 1

2

client_id検索が高速になるように、ドキュメントにインデックスを付けていることを確認してください。distinct(:_id)次に、配列で40KのIDを取得するために使用できます。したがって、最終的なクエリは次のようになりますUser.where(:group_id.in => client.groups.distinct(:_id))。これは、40K ID の配列を取得するために考えられる最も効率的な方法です。それを試してみてください-うまくいくかもしれませんが、誰もがすでに述べたように-それはウェブスケールではありません;)

私が見る限り、特定のクライアントのすべてのユーザーを取得しようとしており、ユーザーは異なるグループを介して複数のクライアントに関連付けられている可能性があります。参加していないクライアントのユーザーを効率的に検索できるようにするために (mongoid では参加していないため)、逆関係のないクライアントを持つユーザーで HABTM を使用できます。だから私は次のようにします:

class Client
  include Mongoid::Document
  include Mongoid::Paranoia
  include Mongoid::Timestamps

  field ...

  has_and_belongs_to_many :users
  has_many :groups, dependent: :delete

  ...
end

class User
  has_and_belongs_to_many :clients
end

次に、ユーザーをグループに関連付けるたびに、グループのクライアントをユーザー (user.clients << clientまたはclient.users << user) に追加して、お互いを認識できるようにしてください。mongoid は Set を使用しているため、重複について心配する必要はありません。ユーザーとクライアントの間の関係が既に存在する場合は、何もしません。次に、クライアントからclient.usersユーザーを検索するか、複数のクライアントのユーザーを検索できます。User.where(:client_ids.in => client_ids)

于 2013-09-19T19:36:31.593 に答える