1

以下は少し不自然な例ですが、要点は理解できます。

次のモデルがあるとしましょう。

class Comment < ActiveRecord::Base
  belongs_to :commentable, :polymorphic => true
end

class Book < ActiveRecord::Base
  has_many :chapters
  has_many :comments, as: :commentable
end

class Chapter < ActiveRecord::Base
  has_many :pages
  has_many :comments, as: :commentable
end

class Page < ActiveRecord::Base
  has_many :paragraphs
  has_many :comments, as: :commentable
end

class Paragraph < ActiveRecord::Base
  has_many :comments, as: :commentable
end

特定の書籍とその子孫に関するすべてのコメントを 1 回のクエリで取得することは可能ですか? つまり、本のモデルだけでなく、章、ページ、および段落に付けられたコメントも含めて、すべてのコメントが必要です。ところで、Book はモデルごとに関連付けを行い、それぞれに対して内部結合を実行できますが、これにより 4 つのクエリが発生します。

Postgres をデータベースとして使用し、Rails 3.2.12 を使用しています。

4

2 に答える 2

1

積極的な読み込みを検討している場合は、ブック側から実行できますが、コメント側からは実行できません。

>> Book.limit(1).includes(:comments).where('comments.id ...') # you'll probably get a book
>> Comment.limit(1).includes(:commentable).where('books.id ...') # you'll get an error

ActiveRecord::EagerLoadPolymorphicError: Can not eagerly load the polymorphic association

あなたはいつでも本のコメントを得るために次のことをすることができます、

>> book = Book.first
>> comments = book.comments
>> comments = Comment.where(commentable_type: 'Book', commentable_id: book.id)
于 2013-02-26T06:05:40.027 に答える
1

これが役立つかどうかはわかりませんが、データベース側からこれに取り組み、これに対処する最善の方法を見つけようとしています。あなたの問題は、あなたのデータベースがどのように見えるかだと思います。SQL からさかのぼって作業できる場合は、それも役立つ場合があります。

これは、堅実なデータベース設計があなたの人生をより簡単にする領域でもあります. 次のテーブル構造があるとします。

CREATE TABLE node_class (
     id int not null unique, 
     node_type label primary key, 
     parent_class int references node_class(id)
);

INSERT INTO node_class (id, node_type, parent_class) 
VALUES (1, 'book', null), (2, 'chapter', 1), (3, 'page', 2), (4, 'paragraph', 3);

CREATE TABLE book_node (
    node_id bigserial primary key,
    node_type int not null,
    parent_class int,
    parent_id int,
    .....
    foreign key (parent_class, parent_id) references book_node(id, node_type)
    foreign key (node_type) references node_class (id),
    foreign key (node_type, parent_class) references node_class(id, parent_class)
);
CREATE TABLE book_comments (
    id bigserial primary key,
    comment_text text not null
);

たとえば、章、ページ番号などを提供するためにブックノードテーブルに接続する他のテーブルがある場合があります。

そこから、ツリーを構築してコメントで結合するクエリを生成するのは非常に簡単です。

WITH RECURSIVE bn_tree (node_id, level, path) as
(
   SELECT node_id, 1, node_id::text
     FROM book_node
    where node_id = ?
UNION ALL
   SELECT n.node_id, level + 1, path || ',' || n.node_id::text
     FROM book_node n
     JOIN bn_tree t ON t.node_id = n.parent
)
SELECT c.* 
  FROM book_comments c
  JOIN bn_tree t ON c.node_id = t.node_id;

SQL がどのように機能するかがわかったら、アプリでより適切に機能するようにデータベースの設計を微調整できると思います。

于 2013-02-26T06:47:55.747 に答える