Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sqlite/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Perl RYO博客引擎-显示多篇文章的标签_Perl_Sqlite_Dancer - Fatal编程技术网

Perl RYO博客引擎-显示多篇文章的标签

Perl RYO博客引擎-显示多篇文章的标签,perl,sqlite,dancer,Perl,Sqlite,Dancer,我正在使用SQLite和Perl Dancer框架编写另一个用于实践的博客引擎 表格如下所示: CREATE TABLE posts ( p_id INTEGER PRIMARY KEY, p_url VARCHAR(255), p_title VARCHAR(255), p_text TEXT, p_date DATETIME DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE tags ( t_id INTEG

我正在使用SQLite和Perl Dancer框架编写另一个用于实践的博客引擎

表格如下所示:

CREATE TABLE posts (
    p_id INTEGER PRIMARY KEY,
    p_url VARCHAR(255),
    p_title VARCHAR(255),
    p_text TEXT,
    p_date DATETIME DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE tags (
    t_id INTEGER PRIMARY KEY,
    t_tag VARCHAR(255),
    t_url VARCHAR(255)
);

CREATE TABLE tags_posts_junction (
    tp_tag INTEGER NOT NULL,
    tp_post INTEGER NOT NULL,
    FOREIGN KEY(tp_tag) REFERENCES tags.t_id,
    FOREIGN KEY(tp_post) REFERENCES tags.p_id
);
所有像Wordpress(或stackoverflow)这样的大人物都可以在主页上的每个问题之后显示标签,我也想实现它。问题是我怎么做

到目前为止,帖子都存储在数据库中,当我需要呈现一个显示最近20篇帖子的页面时,我会将hash reference(
fetchall\u hashref
from
DBI
)传递给模板。那么如何在那里添加标签呢?我当然可以做类似的事情

my $dbh = database->prepare('SELECT * FROM posts ORDER BY p_date DESC 
                    LIMIT 20 OFFSET 0');
$dbh->execute;
my $posts = $dbh->fetchall_hashref('p_date');
foreach my $key (keys $post) {
    my $dbh = database->prepare('SELECT * FROM tags WHERE t_id IN (
                    SELECT tp_tag FROM tags_posts_junction WHERE tp_post = ?)');
    $dbh->execute($post->{"$key"}->{"p_id"});
    my $tags = $dbh->fetchall_hashref(t_id);
    $post->{"$key"}->{"$tag_hash"} = $tags;
};
但这很难看,每页要多查询20次,不是太多了吗?我认为应该有更好的办法


所以问题是如何以最少冗余的方式获得20篇文章的标签

我认为您可以在之前将第一个/外部查询组合起来

my $posts = $dbh->fetchall_hashref('p_date');
使用内部查询,然后将对数据库执行一次而不是20次

您还可以使用DBIx::Simple-简化代码

把这些放在一起会得到如下结果:

my $sql =   'SELECT t.*, p.*
             FROM tags t 
             JOIN tags_posts_junction tpj ON t.t_tag = tpj.t_tag
             JOIN posts p ON p.p_id = tpj.tp_post
             WHERE tpj.tp_post IN (
                SELECT p_id FROM posts ORDER BY p_date DESC 
                LIMIT 20 OFFSET 0
              )';
my $db = DBIx::Simple->connect($dbh);
my $posts = $db->query($sql)->hashes;

将所有p_ID收集到一个数组中,并使用IN而不是=,构建查询,类似这样,假定@pids是您的数组:

my $dbh = database->prepare('SELECT * FROM tags WHERE t_id IN (
                    SELECT tp_tag FROM tags_posts_junction WHERE tp_post IN (' .
                    join(', ', ('?')x@pids).') )');
$dbh->execute(@pids);

虽然您确实应该寻找连接来替换子查询。

添加了查询,但组合示例将非常好,对于DBIx:Simple-不确定我是否有相应的Dancer插件,而且无论如何,我认为我现在应该保留原始SQL,因为它更像是一个学习项目,而不是其他项目。谢谢你的回答。我还认为我可以查询
标签
标签_post_junction
表格,并在应用程序中处理输出。这是三个查询,但仍然不是20个。你不需要为DBIx::Simple添加插件,只需将现有的$dbh传递给DBIx Simple connect方法。当我有更多代表时,我会回来投票支持这一个,
DBIx::Simple
是一件非常好的事情。该查询将为我提供页面上所有标记的数组,不是吗?我担心join会给我carthesian产品,我不想要。事实上,join工作得很好,您的代码示例非常有用。非常感谢,这个问题的查询类似于
SELECT p_date,t_url,t_name FROM posts JOIN tags\u posts\u junction ON p_id=tp_post JOIN tags ON t_id=tp_tag WHERE p_id IN(1,2,3,4)