22

Mongoid を使用して、次のクラスがあるとします。

class Map
  include Mongoid::Document

  embeds_many :locations
end

class Location
  include Mongoid::Document

  field :x_coord, :type => Integer
  field :y_coord, :type => Integer

  embedded_in      :map, :inverse_of => :locations
end


class Player
  include Mongoid::Document

  references_one   :location
end

ご覧のとおり、マップに場所が埋め込まれ、プレーヤーが 1 つの場所を現在の場所として参照する単純なゲーム世界環境をモデル化しようとしています。

このアプローチを使用すると、Player クラスの「場所」属性を参照しようとすると、次のエラーが発生します。

Mongoid::Errors::DocumentNotFound: Document not found for class Location with id(s) xxxxxxxxxxxxxxxxxxx.

私の理解では、これは Location ドキュメントが埋め込まれているため、その埋め込みドキュメント (マップ) の範囲外を参照することが困難になっているためです。これは理にかなっていますが、埋め込みドキュメントへの直接参照をモデル化するにはどうすればよいでしょうか?

4

5 に答える 5

17

マップは独自のコレクションであるため、プレーヤーが参照されている場所を検索するすべてのマップ コレクションを反復処理する必要があります。

埋め込まれたドキュメントに直接アクセスすることはできません。コレクションを通り抜けて、下に向かって作業する必要があります。

すべてのマップを繰り返すのを避けるために、プレイヤー ドキュメントに Location 参照と Map 参照の両方を格納できます。これにより、マップを選択してからその中の場所を選択する基準を連鎖させることができます。これを処理するには、Player クラスにメソッドをコーディングする必要があります。

def location
  self.map.locations.find(self.location_id)
end

そのため、coord 属性を使用する代わりに、プレイヤー ドキュメントに location_id を保存できることを除いて、自分自身の回答と同様です。

もう 1 つの方法は、Map コレクションに Location を埋め込むのではなく、Maps、Locations、および Players を独自のコレクションに配置することです。その後、特別なことをせずに参照関係を使用できます...ただし、階層型データベースを実際に使用しているのは、この時点ではリレーショナルデータベースのようです...

于 2010-11-13T16:18:56.243 に答える
11

MongoDB の問題トラッカーの「仮想コレクション」機能に投票してください。

http://jira.mongodb.org/browse/SERVER-142

これは 2 番目にリクエストの多かった機能ですが、まだリリースの予定はありません。おそらく、十分な数の投票が行われ、1 位になれば、MongoDB チームは最終的にそれを実装するでしょう。

于 2010-12-31T09:24:45.707 に答える
0

既成概念にとらわれず、Location 独自のドキュメントを作成し、Mongoid Alize を使用して、Location ドキュメントからマップ ドキュメントに埋め込みデータを自動的に生成することができます。

https://github.com/dzello/mongoid_alize

この方法の利点は、条件が適切な場合に効率的なクエリが得られることと、他に方法がない場合に元のドキュメントに対する参照ベースのクエリが遅くなることです。

于 2013-04-17T08:39:36.987 に答える
0

私の現在の回避策は、次のことです。

class Map
  include Mongoid::Document

  embeds_many     :locations
  references_many :players, :inverse_of => :map
end

class Player
  referenced_in :map
  field :x_coord
  field :y_coord

  def location=(loc)
    loc.map.users << self
    self.x_coord = loc.x_coord
    self.y_coord = loc.y_coord
    self.save!
  end

  def location
    self.map.locations.where(:x_coord => self.x_coord).and(:y_coord => self.y_coord).first
  end  
end

これは機能しますが、クルーゲのように感じます。

于 2010-10-08T13:31:09.423 に答える