加入的附加条件

时间:2014-11-14 16:00:40

标签: perl postgresql catalyst dbix-class

我有包含文章和用户的表,两者都有多对多映射到第三个表 - 读取。

我在这里要做的是获取特定用户的所有未读文章(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源和虚拟视图来完成,但我还有其他一些可以从中受益的查询,并且我希望避免为每个查询创建虚拟视图。

谢谢, 坎托

2 个答案:

答案 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

谢谢, 坎托