我有一个大型数据集(超过十亿行).数据按日期在数据库中分区.因此,我的查询工具必须在每个查询中指定一个SQL between子句,否则它将必须扫描每个分区..而且,它会在它返回之前超时.
所以..我的问题是,分区数据库中的字段是一个日期..
使用CakePHP,如何在表单中指定"之间"日期?
我正在考虑在表单中执行"start_date"和"end_date",但这可能会给我带来两个问题..如何在链接到表的模型中验证?
如果我正确地关注你:
由于您要验证这些日期,因此当它们隐藏在条件数组中时,它们将更难获取.我建议尝试单独传递这些,然后再处理它们:
$this->Model->find('all', array(
'conditions' => array(/* normal conditions here */),
'dateRange' => array(
'start' => /* start_date value */,
'end' => /* end_date value */,
),
));
Run Code Online (Sandbox Code Playgroud)
您应该希望能够处理beforeFind过滤器中的其他所有内容:
public function beforeFind() {
// perform query validation
if ($queryData['dateRange']['end'] < $queryData['dateRange']['start']) {
$this->invalidate(
/* end_date field name */,
"End date must be after start date"
);
return false;
}
/* repeat for other validation */
// add between condition to query
$queryData['conditions'][] = array(
'Model.dateField BETWEEN ? AND ?' => array(
$queryData['dateRange']['start'],
$queryData['dateRange']['end'],
),
);
unset($queryData['dateRange']);
// proceed with find
return true;
}
Run Code Online (Sandbox Code Playgroud)
我没有尝试Model::invalidate()在查找操作期间使用,所以这可能甚至不起作用.我们的想法是,如果使用FormHelper这些消息创建表单,则应将其返回到表单字段旁边.
如果做不到这一点,您可能需要在控制器中执行此验证并使用Session::setFlash().如果是这样,你也可以摆脱beforeFind并将BETWEEN条件数组放入其他条件.
您可以在模型中编写自定义方法来在日期之间进行搜索:
function findByDateRange($start,$end){
return $this->find('all',array('date >= '.$start,'data >= .'$end));
}
Run Code Online (Sandbox Code Playgroud)
至于验证,您可以使用模型的beforeValidate()回调来验证两个日期。有关此的更多信息,请参见此处。
function beforeValidate(){
if(Validation::date($this->data['Model']['start_date'])){
return false;
}
if(Validation::date($this->data['Model']['end_date'])){
return false;
}
return parent::beforeValidate();
}
Run Code Online (Sandbox Code Playgroud)
这是否回答你的问题?