1. 定義
Mongodbホームページにリレーションの定義が書いてあります。
- Embeds One
Embeds One
One to one relationships where the children are embedded in the parent document are defined using Mongoid’s embeds_one and embedded_in macros.
- Has One
Has One
One to one relationships where the children are referenced in the parent document are defined using Mongoid’s has_one and belongs_to macros.
Embeds OneとHas Oneの違いはデータの持ち方です。
- 
Embeds One
 parentのデータの中にchildrenのデータが入っています。そのため、parentからchildrenのデータを取りたいとき、別のクエリーが必要ないです(処理時間が少ない)
- 
Has One
 parentのデータの中にchildrenのデータが入っていません。そのため、parentからchildrenのデータを取りたいとき、別のクエリーが必要です。
p.s.: embeds-manyとhas-manyも上に書いた違いがあります。
2.どれが良いか?
Mongodbホームページの事例を見ましょう!
例1:
class Band
  include Mongoid::Document
  has_many :albums, dependent: :delete
end
例2:
class Band
  include Mongoid::Document
  embeds_many :albums
end
両方はBandとAlbumの関係を定義しています。
embeds_manyとhas_manyのどちらを使いますか?
場合によって違います。
仕様が決まらないと、どちらを使うか選べません。
なので私は、以下の二つのケースを考えてから決めることにしています
 質問1. parentとchildrenを一緒に使うケースが多いですか?
質問1. parentとchildrenを一緒に使うケースが多いですか?
- もし多かったらembeds_*を使った方が良いです。
 - 逆に、少なかったら、has_*を使った方が良いです。詳細
 質問2.parentがなくなると、childrenが存在する意味がなくなるか?
質問2.parentがなくなると、childrenが存在する意味がなくなるか?
 - もしchildrenの存在する意味がまだあるなら、has_*を使った方が良いです。
 - 逆に、childrenの存在する意味がもうなくなるなら、embeds_*を使った方が良いです。
2つの質問を考えてもまだ決められない時は
has_*を使う場合の、クエリーコストを考えたり、
embeds_*を使う場合の、重複されるデータ量のことを考えます。詳細
embeds_* :
- メリット:
- childrenのデータを取得するスピードが早い
- n+1 問題が起こりません
 
- デメリット:
- 集計、分析が難しい。ドキュメントに直接アクセスすることができないから。
- ネストのデータは管理しにくい
- 重複するデータが増える可能性が高い
- ドキュメントのリミットがありますので増え続けるようなデータをembeds_*にしたら注意しないといけない。詳細
 
has_* :
- メリット:
- 集計、分析が比較的簡単です
- 正規化(normalized data model)
 
- デメリット:
- childrenのデータを取得する場合、クエリーが必要です。
- n+1 問題に気を付けないといけない
3. サンプル(実際に考えてみる)
- 記事とタグはembeds_、has_?
- 
質問1を答える: - 記事を取得するたびに、タグを取得するケースが多発しそうな時、embeds_*が候補に上がります。
- 記事のデータだけ取得するケースが多い場合、has_*でも大丈夫だと思います
 
- 記事を取得するたびに、タグを取得するケースが多発しそうな時、
- 
質問2を答える: - 記事を削除して、タグの存在する意味がなくなることはないので、has_*を使います。
 
- 記事を削除して、タグの存在する意味がなくなることはないので、
なので僕はhas_*にします。
2.PostとCommentはembeds_、has_?
- 質問1を答える:
- SNSの場合、Postを取得するたびに、commentも取得します。embeds_*で大丈夫です
- comment数を数えたい、commentの意味を分析したい、like数を数えたい。この場合は、has_*もよさそうです。
 
- SNSの場合、Postを取得するたびに、commentも取得します。
- 質問2を答える
- Postを削除すると、commentの意味がなくなってしまいます。embeds_*を使う方がいいです。
 
- Postを削除すると、commentの意味がなくなってしまいます。
なのでembeds_*にします。
3.他のは「記事とアイキャッチ」、「人とアドレス」
