Случайные результаты запроса на основе сеанса

У меня есть таблица профилей, в которой я хотел бы иметь списки профилей в случайном порядке, которые я выполнил следующим образом:

$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'));
Другие вопросы по тегам