我有包含文章和用户的表,两者都有多对多映射到第三个表 - 读取。
我在这里要做的是获取特定用户的所有未读文章(user_id
不在表reads
中)。
我的查询是获取所有文章,但阅读的文章被标记,如果我可以过滤掉它们(user_id字段包含有问题的用户的ID)。
我有一个像这样的SQL查询:
SELECT articles.id, reads.user_id
FROM articles
LEFT JOIN
reads
ON articles.id = reads.article_id AND reads.user_id = 9
ORDER BY articles.last_update DESC LIMIT 5;
以下是:
articles.id | reads.user_id
-------------------+-----------------
57125839 | 9
57065456 |
56945065 |
56945066 |
56763090 |
(5 rows)
这很好。这就是我想要的。
我希望使用我的文章模型在Catalyst中获得相同的结果,但我找不到任何向JOIN子句添加条件的选项。
您知道如何将AND X = Y
添加到DBIx JOIN吗?
我知道这可以通过自定义resoult源和虚拟视图来完成,但我还有其他一些可以从中受益的查询,并且我希望避免为每个查询创建虚拟视图。
谢谢, 坎托
答案 0 :(得分:1)
我甚至不知道Catalyst
是什么,但我可以破解SQL查询:
select articles.id, reads.user_id
from
articles
left join
(
select *
from reads
where user_id = 9
) reads on articles.id = reads.article_id
order by articles.last_update desc
limit 5;
答案 1 :(得分:1)
我有一个解决方案。
它并不直接,但它比虚拟视图更好。
http://search.cpan.org/dist/DBIx-Class/lib/DBIx/Class/Relationship/Base.pm#condition
上面描述了如何在JOIN子句中使用条件。 但是,我的情况在这些条件中需要一个变量,默认情况下在模型中不可用。 因此,绕过一些模型概念并为其引入变量,我们有以下内容。
在模型文件中
our $USER_ID;
__PACKAGE__->has_many(
pindols => "My::MyDB::Result::Read",
sub {
my $args = shift;
die "no user_id specified!" unless $USER_ID;
return ({
"$args->{self_alias}.id" => { -ident => "$args->{foreign_alias}.article_id" },
"$args->{foreign_alias}.user_id" => { -ident => $USER_ID },
});
}
);
控制器中的
$My::MyDB::Result::Article::USER_ID = $c->user->id;
$articles = $channel->search(
{ "pindols.user_id" => undef } ,
{
page => int($page),
rows => 20,
order_by => 'last_update DESC',
prefetch => "pindols"
}
);
将获取所有未读文章,并产生以下SQL。
SELECT me.id, me.url, me.title, me.content, me.last_update, me.author, me.thumbnail, pindols.article_id, pindols.user_id FROM (SELECT me.id, me.url, me.title, me.content, me.last_update, me.author, me.thumbnail FROM articles me LEFT JOIN reads pindols ON ( me.id = pindols.article_id AND pindols.user_id = 9 ) WHERE ( pindols.user_id IS NULL ) GROUP BY me.id, me.url, me.title, me.content, me.last_update, me.author, me.thumbnail ORDER BY last_update DESC LIMIT ?) me LEFT JOIN reads pindols ON ( me.id = pindols.article_id AND pindols.user_id = 9 ) WHERE ( pindols.user_id IS NULL ) ORDER BY last_update DESC: '20'
当然你可以跳过分页,但我在我的代码中有它,所以我把它包含在这里。
特别感谢irc.perl.org和https://blog.afoolishmanifesto.com/posts/dbix-class-parameterized-relationships/上#dbix-class的 deg 。
谢谢, 坎托