我想限制使用可包含的更深层关联返回的字段。
我的协会:
游戏有很多评论
分页和可包含的代码:
$this->paginate = array(
'conditions' => $conditions,
'fields' => array(
'Game.id', 'Game.name',
'Publisher.id', 'Publisher.name'
),
'contain' => array(
'Game' => array(
'Review' => array(
'fields' => array('Review.id', 'ROUND(AVG(Review.score),1)')
)
),
)
);
$games = $this->paginate('Game');
目前,返回Review
表中的所有字段。永远不会返回'ROUND(AVG(Review.score),1)'
。如何指定从Review
关联返回的字段?
SQL转储。第一个是搜索一个游戏,第二个是搜索返回三个游戏。
SELECT `Review`.`id`, `Review`.`review_text`, `Review`.`score`, `Review`.`user_id`, `Review`.`game_id`, `Review`.`created`, `Review`.`platform_id`, (ROUND(AVG(`Review`.`score`),1)) AS `Review__average_score` FROM `videogamedb`.`reviews` AS `Review` WHERE `Review`.`game_id` = (55)
SELECT `Review`.`id`, `Review`.`review_text`, `Review`.`score`, `Review`.`user_id`, `Review`.`game_id`, `Review`.`created`, `Review`.`platform_id`, (ROUND(AVG(`Review`.`score`),1)) AS `Review__average_score` FROM `videogamedb`.`reviews` AS `Review` WHERE `Review`.`game_id` IN (55, 56, 57)
答案 0 :(得分:0)
我认为您的数组配置有点错误,请尝试:
$this->paginate = array(
'Game' => array(
'conditions' => $conditions,
'fields' => array(
'Game.id', 'Game.name',
'Publisher.id', 'Publisher.name'
),
'contain' => array(
'Review' => array(
'fields' => array('Review.id', 'ROUND(AVG(Review.score),1)')
)
)
)
);
$games = $this->paginate('Game');
顺便说一句,根据个人经验,在查询中指定字段并不总能加快速度(当然对于少量字段),假设这是这样做的动机。它确实减少了内存占用,但这只相对于记录的原始大小和返回的记录数。
答案 1 :(得分:0)
不是完整的答案,而是试图让它发挥作用:)
首先,尝试将“Game”模型添加到Controller的$uses
数组中(如果尚未包含),并重新组织分页数组(如Sam先前所建议的那样),所以你会对游戏模型本身进行分页。
然后,为计算得分创建虚拟字段可能会有所帮助,但“评论”的结果需要进行分组,否则您将无法计算平均分数。
我无法测试这个,但值得尝试
像这样的东西;public $uses = array(
'Game',
// other models
);
public function myfunction()
{
$this->Game->Review->virtualFields['average_score'] = 'ROUND(AVG(Review.score),1)';
$this->paginate = array(
'Game' => array(
'fields' => array(
'Game.id',
'Game.name',
'Publisher.id',
'Publisher.name'
),
'contain' => array(
'Review' => array(
'fields' => array(
'Review.game_id,
'Review.average_score',
),
'group' => array(
'Review.game_id,
),
)
)
)
);
// Conditions can be passed to paginate,
// that way you can specify 'paginate' at
// one place and don't have to modify it
// to include the conditions
$games = $this->paginate('Game', $conditions);
}
显然,Containable行为不喜欢group-by子句;有关详细信息,请参阅此票证:Containable behavior does not implement 'group' option
CakePHP允许您手动指定联接:Joining Tables
为简化操作并防止必须为所有字段添加“分组依据”,请在数据库中创建一个简单的数据库视图;
CREATE VIEW review_scores AS
SELECT
game_id,
ROUND(AVG(score),1) AS average_score,
COUNT(id) AS total_reviews
FROM
reviews
GROUP BY
game_id;
如果你不熟悉这个;数据库“视图”基本上是一个“存储查询”,可以像访问常规表一样进行访问。见Create View
然后,使用新创建的数据库视图作为源表,使用“手动”连接。在你的情况下,这看起来像这样;
$this->paginate = array(
'Game' => array(
'fields' => array(
'Game.id',
'Game.name',
'Publisher.id',
'Publisher.name',
'ReviewScore.average_score',
'ReviewScore.total_reviews',
),
'joins' => array(
array(
'table' => 'review_scores',
'alias' => 'ReviewScore',
'type' => 'LEFT',
'conditions' => array(
'ReviewScores.game_id = Game.id',
)
)
)
)
);
希望这有帮助