好的,我是DBIx :: Class的新手。我有一对多的关系设置,如下:
User -> has_many -> Addresses
好的,好的。我可以进行查询,并将其称为预取JOINed表,如下所示:
Foo::DBIC->storage->debug(1); # output SQL to STDOUT
my $user = Foo::DBIC->resultset('Users')->search({}, {
prefetch => [ 'addresses' ],
join => [ 'addresses' ],
rows => 1
})->single;
for my $address ($user->addresses->all) {
say $address->zip_code;
}
两个表,一个SQL查询(通过调试验证)。一切都很好。
然而,现在,假设我想在Foo :: DBIC :: Result :: Users中编写一个或两个重载方法,根据某些条件返回地址的子集。这是我添加到Users类的内容:
sub home_addresses {
my $self = shift;
return $self->search_related('addresses', { address_type => 'home' });
}
sub business_addresses {
my $self = shift;
return $self->search_related('addresses', { address_type => 'business' });
}
我可以像这样调用这些重载,它们可以工作:
for my $address ($user->home_addresses->all) {
say $address->zip_code;
}
然而,这个忽略这个事实,我已经预取了我的连接,它执行了额外的查询(好像我没有预取并加入任何东西)。
所以,我的问题是:如何定义一个返回相关表子集的重载方法,但是使用已经预取的连接? (只需在预取中添加WHERE子句)...
我的问题是,如果我有很多重载方法返回相关的表子集,我的查询计数会爆炸;特别是如果我在一个循环中调用它们。
我有理由这样做,当然是丑陋的。我的现实生活模式比用户和地址更多,很多,很多,而且我试图尽可能地抽象出丑陋。
谢谢!
答案 0 :(得分:0)
sub home_addresses {
my $self = shift;
my $addresses = $self->addresses;
my $home_addresses;
while (my $row = $addresses->next()) {
push @$home_addresses, $row if $row->address_type() eq 'home';
}
my $home_rs = $addresses->result_source->resultset;
$home_rs->set_cache( $home_addresses );
$home_rs;
}
或者,如果有很多类似的地址类型:
sub addresses_by_type {
my $self = shift;
my $addresses = $self->addresses;
my $type;
my $rs_type;
while (my $row = $addresses->next()) {
push @{$type->{"".$row->address_type}},
$row;
}
for (keys %$type) {
my $new_rs = $addresses->result_source->resultset;
$new_rs->set_cache( $type->{$_} );
$rs_type->{$_} = $new_rs
}
return $rs_type
}
您可以通过以下方式访问“主页”地址:
while (my $r = $user->next) {
use Data::Dumper;
local $Data::Dumper::Maxdepth = 2;
print $r->username,"\n";
my $d = $r->addresses_by_type();
my $a = $d->{home};
while (defined $a and my $ar = $a->next) {
print $ar->address,"\n";
}
}
答案 1 :(得分:-1)
你可以尝试这样的事情:
sub home_addresses {
my $self = shift;
my $return = [];
my @addresses = $self->addresses->all();
foreach my $row (@addresses) {
push @$return, $row if $row->address_type() eq 'home';
}
return $return;
}