- 'author' has-many 'books'
- 'book' has-many 'chapters'
みたいなありがちな DB で
- 2 authors
- each author has 2 books
- each book has 3 chapters
みたいなテーブルを作ってMulti-step-prefetch をためしてみたんですけど,
my @authors = $db->resultset('author')->search(
{
},
{
prefetch => { 'book' => 'chapter' },
},
)->all;
foreach my $author (@authors) {
print $author->name, "\n";
foreach my $book ($author->books) {
print "\t", $book->name, "\n";
foreach my $chapter ($book->chapters) {
print "\t\t", $chapter->name, "\n";
}
}
}の結果が,
Larry Wall
Programming Perl
C1: An Overview of Perl
C2: Bits and Pieces
C3: Unary and Binary Operators
Perl Resource Kit
C2: Programming with Perl Modules
C3: Advanced Perl Programming
Damian Conway
Object Oriented Perl
C1: Introduction of Object Oriented Programming
C2: Introduction of Perl Programming
C3: Object Oriented Perl Programmingchapter 1個と book 1個が lost してる。吐いている SQL は問題なさそうなので(CLI でためしたらうまくとれるんで)オブジェクトの結果からの再構築がうまくいってないぽいです。コードが追いづらかったんで報告してない。
いまのところ has-many なクエリを多段 prefetch するのはあんましよろしくない(そもそも resultset_attributes な条件つけたりすると競合しそうだし)みたいです。
おまけ
has-many な関連レコードを取得するとき,なーんとなく primary column(s) 順にソートされてることを期待してたんですけどもちろんそんなことはないんですよね,ええ。今日はまりました。
そんなとき有用なのが,id:nekokak さんご推薦の resultset_attributes
(resultset_attributes - Hatena::Diary::Neko::kak 500 Internal Server Error)。
ですが私みたいに全テーブルの primary key に id のように同じ名前をつける癖のある人は,
__PACKAGE__->resultset_attributes({ order_by => 'me.id'});
のように「me.」をつけたほうがベター。search_related とかすると id という名称が ambiguous になってしまうんで。ただ弊害はあるかもしんない。