【问题标题】:CakePHP - Find and count how many associated records existCakePHP - 查找并计算存在多少关联记录
【发布时间】:2014-05-22 19:49:24
【问题描述】:

我正在尝试执行搜索,作为条件,它必须只返回具有一定数量的关联记录的记录。

目前我有一个模型(Bands)和一个关联模型 thourgh hasmany(Songids)。每个乐队可以有很多歌曲。

在这个特定的搜索中,我想返回 4 个乐队的结果,这些乐队有至少 10 个相关联的歌曲名称。

我尝试在查找过程中使用“HAVING”条件执行此操作,并在 Songid 模型中使用“COUNT(Songid.band_id)”的虚拟字段执行此操作,但它只返回总数,而不仅仅是所选字段。

我怎样才能做到这一点?我在想类似的东西:

    $random = $this->Band->find('all', array(
            'fields' => array('Band.band'),
            'order' => 'rand()',
            'limit' => 4,
            'contain' => array(
                'Songid' => array(
                    'conditions' => array(
                        'band_id COUNT' => 2)
                )
            )
        )
    );

最后一部分“'band_id COUNT' => 2”应该可以解决问题,但我无法让它发挥作用。 有什么想法吗?


编辑:我可以先查找所有,然后再查找每个关联模型的计数,但我正在寻找“一个查找,不处理”的解决方案。

【问题讨论】:

    标签: mysql cakephp


    【解决方案1】:

    'band_id COUNT' => 2 不是 CakePHP ORM 能理解的,如果你必须使用像 COUNT(table) >= x 这样的适当的 SQL sn-p。

    但是conditions 总是映射到WHERE,而WHERE COUNT 在 MySQL 中不起作用(您可能已经知道,正如您使用 HAVING 所提到的那样)。

    总是...

    计数器缓存

    在这种特殊情况下,您可以使用counter cache 字段

    class Songid extends AppModel {
        // ...
    
        public $belongsTo = array(
            'Band' => array(
                'counterCache' => true,
            )
        );
    
        // ...
    }
    

    这样您就可以使用以下简单条件轻松查询关联记录的数量:

    $this->Band->find('all', array(
        // ...
        'conditions' => array(
            'Band.songid_count >=' 10
        )
    ));
    

    使用连接

    不使用计数器时,您必须手动加入关联的表,因为它们不会自动包含在内,而是在单独的查询中使用。

    加入后,您可以安全地查询相关模型:

    $this->Band->find('all', array(
        'joins' => array(
            array(
                'table' => 'songids',
                'alias' => 'Songid',
                'type' => 'LEFT',
                'conditions' => array('Band.id = Songid.band_id')
            )
        ),
        // ...
        'group' => 'Band.id HAVING COUNT(Songid.id) >= 10'
    ));
    

    【讨论】:

    • 如果我选择添加 countercache 选项,即使我删除了相关模型的单个记录,这个数字也会自动更新?比如我时不时要通过$this->Band->Songid->delete删除songid数据库的一些记录。这会更新那个缓存吗?顺便说一句,我只是好奇地问,我去了手动加入解决方案,它工作得很好。非常感谢!
    • 嗯,它在本地运行得很好。当我上传到制作服务器(哪些乐队有 10k 条记录,而 songids 有 100k 条记录)时,我的网站崩溃了。猜猜我要试试 countercache 解决方案!
    • @Andres 是的,这正是计数器缓存的作用。 10K/100K 不应该使服务器崩溃,但它可能会有点慢,因为它需要处理 all 行以进行计数和随机排序。使用正确索引的计数器缓存应该更快(假设有 10 多首歌曲的乐队少于 10K),因为它会在订购前减少集合,当然不再需要计数。
    猜你喜欢
    • 2016-08-12
    • 2011-10-23
    • 1970-01-01
    • 1970-01-01
    • 2012-06-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多