Случайные результаты запроса на основе сеанса
У меня есть таблица профилей, в которой я хотел бы иметь списки профилей в случайном порядке, которые я выполнил следующим образом:
$this->paginate = array('User' => array('conditions'=>array('User.userstanding_id'=>'1'), 'order' => 'RAND()', 'limit' => '10'));
Единственная функциональность, которая отсутствует в этом, заключается в том, что я хотел бы, чтобы профили следовали последовательно, чтобы на следующей странице не было дубликатов и даже некоторые профили вообще не просматривались, когда вы просматриваете все страницы.
То, что я ищу, - это способ найти случайную начальную точку для запроса, а затем разбить ее по порядку с этой начальной точки. Может быть, за сеанс?
2 ответа
MySQL RAND()
Функция может принимать целое число в качестве аргумента для использования в качестве начального числа, всегда приводя к одному и тому же результату:
Чтобы продемонстрировать это, вот таблица с 3 строковыми записями в одном столбце:
mysql> select * from chartest;
+--------+
| string |
+--------+
| AA |
| AB |
| BB |
+--------+
3 rows in set (0.00 sec)
Если я использую 1 в качестве моего начального значения для rand()
в моем ORDER BY
он всегда будет приводить к одному и тому же результату:
mysql> select * from chartest order by rand(1);
+--------+
| string |
+--------+
| BB |
| AA |
| AB |
+--------+
3 rows in set (0.00 sec)
mysql> select * from chartest order by rand(1);
+--------+
| string |
+--------+
| BB |
| AA |
| AB |
+--------+
3 rows in set (0.00 sec)
Если я поменяю семя на 2, порядок изменится:
mysql> select * from chartest order by rand(2);
+--------+
| string |
+--------+
| AB |
| BB |
| AA |
+--------+
3 rows in set (0.00 sec)
Выбирая свое семя
Вы можете преобразовать идентификатор сеанса пользователя в целое число и передать его этой функции, чтобы для этого сеанса результаты всегда были упорядочены одинаково.
Если, например, идентификатор сеанса является хешем MD5, чтобы избежать необходимости иметь дело с большими (160-битными) целыми числами, которые представляют эти значения, просто удалите символы из строки (используя, например, preg_replace ('/[^\d\s]/', '', $sessionid);
). Затем возьмите первые 5 или около того цифр и преобразуйте их в (int)
использовать в качестве вашего семени:
$seed = substr($numeric_id, 0, 5);
Обновить
Чтобы передать параметр в RAND()
Функция при использовании CakePHP, чтобы убедиться, что он рассматривается как целое число, а не строка, попробуйте использовать следующий синтаксис в вашем $conditions
массива order
:
'order' => 'RAND(CAST('.$seed.' AS SIGNED))'
Я не эксперт в CakePHP, но я представляю, что если вы запустите функцию RAND на основе сеанса, тогда функция paginate будет работать от страницы к странице, используя значение семени сеанса.
например
назначить семя при создании сеанса, просто используйте генератор случайных чисел, чтобы сделать это.
$this->paginate = array('User' => array('conditions'=>array('User.userstanding_id'=>'1'), 'order' => 'RAND('.$_SESSION['rndSeed'].')', 'limit' => '10'));