Reputation:
I have a large data set (over a billion rows). The data is partitioned in the database by date. As such, my query tool MUST specify an SQL between clause on every query, or it will have to scan every partition.. and well, it'll timeout before it ever comes back.
So.. my question is, the field in the database thats partitioned is a date..
Using CakePHP, how can I specify "between" dates in my form?
I was thinking about doing "start_date" and "end_date" in the form itself, but this may bring me two a second question.. how do I validate that in a model which is linked to a table?
Upvotes: 5
Views: 12910
Reputation: 6403
if you want to find last 20 days data .
$this->loadModel('User');
//$this->User->recursive=-1;
$data=$this->User->find('all', array('recursive' => 0,
'fields' => array('Profile.last_name','Profile.first_name'),'limit' => 20,'order' => array('User.created DESC')));
other wise between two dates
$start = date('Y-m-d') ;
$end = date('Y-m-d', strtotime('-20 day'));
$conditions = array('User.created' =>array('Between',$start,$end));
$this->User->find("all",$conditions)
Upvotes: 1
Reputation: 11202
If I am following you correctly:
Since you want to validate these dates they will be harder to grab when they are tucked away inside your conditions array. I suggest trying to pass these in separately and then dealing with them later:
$this->Model->find('all', array(
'conditions' => array(/* normal conditions here */),
'dateRange' => array(
'start' => /* start_date value */,
'end' => /* end_date value */,
),
));
You should hopefully be able to handle everything else in the beforeFind
filter:
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;
}
I have not tried using Model::invalidate()
during a find operation, so this might not even work. The idea is that if the form is created using FormHelper
these messages should make it back next to the form fields.
Failing that, you might need to perform this validation in the controller and use Session::setFlash()
. if so, you can also get rid of the beforeFind
and put the BETWEEN
condition array in with your other conditions.
Upvotes: 8
Reputation: 28205
You could write a custom method in your model to search between the dates:
function findByDateRange($start,$end){
return $this->find('all',array('date >= '.$start,'data >= .'$end));
}
As far as validating, you could use the model's beforeValidate()
callback to validate the two dates. More info on this here.
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();
}
Does that answer your question?
Upvotes: 0