如何最小化CakePHP中的“包含”查询?

时间:2012-10-24 10:38:37

标签: cakephp has-many belongs-to containable

我有三个模型,用户评论页面

用户 有很多 评论评论 属于

所有模型都使用containable行为,默认为recursive -1

如果我在评论上调用find()查询,并使用包含 Page 模型字段的包含请求,则会正确返回结果使用单个查询,自动将 Page 表加入用户。

如果我从用户模型(包含 评论 Comment.Page )调用类似查询,结果是查询来源评论,然后是每条评论的查询,以获取相关的页面

有没有办法配置模型来维持JOIN优化?我假设相关模型上的belongsTo声明( Comments )将跟随主机模型( Users )。

更新

我应该澄清,我的问题使用了我的实际案例研究的简化版本。虽然我需要的最小解决方案包括此初始模型 hasMany 模型 belongsTo 模型结构,我也在寻找一个或多个 belongsTo 模型链的解决方案(我虽然会自动使用LEFT JOIN,因为这是可行的)。

5 个答案:

答案 0 :(得分:2)

嗯那很有意思。这是一种应该在核心中实施的优化:)

无论如何,我认为你可以通过稍微不同的方式构建查询来获得相同的结果(可能格式不同):

$this->User->Comment->find('all', array(
  'conditions' => array(
    'Comment.user_id' => $userId
  ),
  'contain' => array(
    'User',
    'Page'
  )
));

通过从Comment模型中搜索,它应该使用两个左连接来连接数据,因为它们都是1:1关系。注意:结果数组可能与从用户模型搜索时的结果略有不同。

答案 1 :(得分:1)

您是否在询问是否有更简单的方法来包含所有查询?如果要包含当前控制器中的所有内容。您可以在beforeFilter()回调中执行包含,它将应用于该控制器中的所有查询。

答案 2 :(得分:1)

我不太确定我是否理解你的问题,但我认为你对于评论的许多sql调用有问题 - >页面链接?如果这是正确的,那么

  1. 尝试linkable behaviour,它可以减少sql调用并且几乎可以像
  2. 一样工作
  3. 或者如果你想要几乎相同的数据,那么在特定的模型中创建一个函数,你可以从中获得hte sql调用(例如Comment-Model),并通过{{1}从用户模型中调用它。 }}
  4. 希望有所帮助

    编辑:我想到的一件事。您可以将关联数组中的连接类型更改为$this->Comment->myFindFct($params);,这样可以将蛋糕单独调用相关模型

答案 3 :(得分:1)

我发现一个好方法是创建一个custom find method

作为一个例子,我在你的用户模型中创建了一个名为_findUserComments()的方法。然后,您将在此方法中执行所有连接,包含等。然后在您的控制器中,无论您需要获取所有用户的评论,都可以这样称呼它:

$this->User->find('UserComments', array(
    "conditions" => array(
        'User.id' => $userId
    )
));

我希望这会有所帮助。

答案 4 :(得分:1)

如果模型定义如下:

  1. 评论模型属于Page和User。
  2. Page属于User并有很多评论。
  3. 用户有很多页面和评论
  4. 代码贝娄将返回一个已加入的查询:

    $this->loadModel('Comment');
    $this->Comment->Behaviors->attach('Containable');
    $queryResult = $this->Comment->find('all', array(
       'contain' => array(
           'User', 
           'Page'
        )
    ));
    

    下面的代码将返回两个查询。页面和用户加入一个查询,并在另一个查询中加入所有评论

    $this->loadModel('Page');
    $this->Page->Behaviors->attach('Containable');
    $queryResult = $this->Page->find('all', array(
       'contain' => array(
            'User', 
        'Comment'
       )
    ));
    

    并且下面的代码将返回三个查询,每个模型一个:

    $this->loadModel('User');
    $this->User->Behaviors->attach('Containable');
    $queryResult = $this->User->find('all', array(
        'contain' => array(
            'Page', 
            'Comment'
        )
    ));