使用Doctrine Symfony清除仅一个实体/存储库的结果缓存

3
我有一个消息实体仓库,我想为获取这些消息的查询结果缓存结果。但是,提取仓库函数将结果分页,因此涉及偏移量和限制。
我唯一想到的方法是生成并记住另一个缓存条目中的每个缓存ID,然后使用该条目使它们全部无效,从而仅使一个实体/仓库的结果缓存失效。有更好的解决此问题的方法吗?
编辑:我刚刚发现,缓存ID不用于唯一查询,而是缓存所有查询,即使它们的变量发生了变化。
public function getMessages($offset, $limit, $search = null){
    $builder = $this->createQueryBuilder('m')
        ->orderBy('m.id', 'DESC')
        ->setFirstResult($offset)
        ->setMaxResults($limit);

    if($search !== null){
        $builder->where('m.title LIKE :searchQuery OR m.content LIKE :searchQuery')
            ->setParameter('searchQuery', '%'.$search.'%');

        return $builder->getQuery()->getResult(Query::HYDRATE_ARRAY);
    } else {
        return $builder->getQuery()
            ->useResultCache(true, null, 'message_messages')
            ->getResult(Query::HYDRATE_ARRAY);
    }
}

我有4个消息,设置每页显示2条消息。所以第一个查询的偏移量为0,限制为2,第二个查询的偏移量为2,也限制为2。

现在发生的情况是,两个查询都被缓存到单个缓存ID下。我从phpMyAdmin进行了更改,两个页面都没有变化,这意味着它们都使用了缓存。当我无效的“message_messages”缓存ID时,两个页面都发生了变化,phpMyAdmin所做的更改现在可见。

我只想说,这正是我希望它工作的方式。但我不确定它是否属于某种未定义行为?


你找到解决方案了吗?还是还在寻找中? - Charles-Antoine Fournel
为了使您的缓存具有唯一性,您应该在偏移量之后构建缓存名称,因此如果您当前的偏移量为0,则您的缓存名称变为message_messages_0等。尝试使用->useResultCache(true, null, 'message_messages_'.$offset)。我希望我理解得正确!?还请查看:http://www.inanzzz.com/index.php/post/ck9l/using-doctrine-apc-caching-with-query-builder-in-symfony - BentCoder
1
@Charles-AntoineFournel,我以为我找到了一个解决方案,但BentCoder说我应该为每个建立唯一的ID,根据我检查和在帖子的编辑中描述的情况,这个ID将所有查询分组。当我为多个偏移使用单个ID时,它们仍然都会被缓存,并且我可以通过清除这个ID来使所有页面失效。 - Mr_KoKa
1
@BentCoder,根据我的检查,似乎不需要为每个偏移量设置唯一的ID,只需在单个ID下它仍然可以缓存每个页面(我可以通过清除该ID来清除所有页面的缓存)。 - Mr_KoKa
@Mr_KoKa,我有点困惑,让我们暂时忽略你面临的问题,专注于你需要什么。简单来说,你能告诉我你需要什么吗?例如:“当我这样做时,应该发生这种情况。” - BentCoder
@BentCoder 我想要对缓存进行分组,以便稍后可以清除它。如果我按照模式m_m_$offset构建我的缓存ID,那么我将拥有m_m_0、m_m_1等等。如果我想要使其无效,我需要循环遍历所有这些缓存ID,因此我需要保存它们的ID,以便可以循环遍历。 现在我所做的是使用一个缓存ID,它似乎可以工作,因此当我获取偏移量为0的消息时,我会得到缓存结果,同样适用于偏移量1,它们不会重叠,因此在获取偏移量1的结果之后,偏移量0的结果仍然存在于缓存中,我可以通过清除m_m来简单地清除它们。(m_m代表message_messages) - Mr_KoKa
1个回答

1
我知道这对其他人来说可能很明显,但是我认为如果我使用带有id的ResultCache,例如“resultCacheId1”,然后再次使用相同的缓存,第二次使用会覆盖第一个缓存。但是我发现它被分组在一个缓存id下,像这样:
与我的问题相同的函数,我将仅删除$search和$limit参数以简化它:
public function getMessages($offset){
    $builder = $this->createQueryBuilder('m')
        ->orderBy('m.id', 'DESC')
        ->setFirstResult($offset)
        ->setMaxResults($limit)
        ->getQuery()
        ->useResultCache(true, null, 'message_messages')
        ->getResult(Query::HYDRATE_ARRAY);

}

为了测试目的,我使用以下代码来获取并查看缓存中的内容:

$em->getConfiguration()->getResultCacheImpl()->fetch('message_messages')

如果我像这样只使用一次函数 getMessages(0),它将显示在缓存中:

array:1 {
    "SELECT ... FROM message m0_ ORDER BY m0_.id DESC LIMIT 2 OFFSET 0-a:0:{}-a:0:{}" => array:2 {
        0 => array:4 {id: 6, title: '...', content: '...', date: '...'},
        1 => array:4 {id: 5, title: '...', content: '...', date: '...'},
    }

}

当我再次这样使用它时getMessages(1),它将向'message_messages'缓存ID添加另一个条目:

array:1 {
    "SELECT ... FROM message m0_ ORDER BY m0_.id DESC LIMIT 2 OFFSET 0-a:0:{}-a:0:{}" => array:2 {
        0 => array:4 {id: 6, title: '...', content: '...', date: '...'},
        1 => array:4 {id: 5, title: '...', content: '...', date: '...'},
    },
    "SELECT ... FROM message m0_ ORDER BY m0_.id DESC LIMIT 2 OFFSET 2-a:0:{}-a:0:{}" => array:2 {
        0 => array:4 {id: 4, title: '...', content: '...', date: '...'},
        1 => array:4 {id: 3, title: '...', content: '...', date: '...'},
    }

}

我只需使 'message_messages' 缓存 id 无效即可使所有内容都无效。因此,我不需要为每个唯一的偏移量构建缓存 id,例如 message_messages_0、message_messages_1、message_messages_2 等,然后在循环中使它们全部无效。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接