Случайные результаты запроса на основе сеанса - PullRequest
2 голосов
/ 19 апреля 2011

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

$this->paginate = array('User' => array('conditions'=>array('User.userstanding_id'=>'1'), 'order' => 'RAND()', 'limit' => '10')); 

Единственная функциональность, которая отсутствует в этом, - это то, что я хотел бы, чтобы профили следовали последовательно, чтобы на следующей странице не было дубликатов, и даже некоторые профили вообще не просматривались, когда вы проходите через все страницы.

То, что я ищу, - это способ найти случайную начальную точку для запроса, а затем разбить ее по порядку с этой начальной точки. Может быть, за сеанс?

Ответы [ 2 ]

2 голосов
/ 19 апреля 2011

Функция MySQL RAND() может принимать целое число в качестве аргумента для использования в качестве начального числа, всегда приводя к одному и тому же результату:

Чтобы продемонстрировать это, вот таблица с тремя одиночными-колонка строковых записей в нем:

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, чтобы убедиться, что он рассматривается как целое число, а не строка, попробуйте использовать следующий синтаксис в order массива $conditions:

'order' => 'RAND(CAST('.$seed.' AS SIGNED))' 
1 голос
/ 19 апреля 2011

Я не эксперт в CakePHP, но я думаю, что если вы запустите функцию RAND на основе сеанса, то функция разбивки на страницы будет работать от страницы к странице, используя значение семени сеанса.

например,

назначить начальное число при создании сеанса, просто используйте генератор случайных чисел, чтобы сделать это.

 $this->paginate = array('User' => array('conditions'=>array('User.userstanding_id'=>'1'), 'order' => 'RAND('.$_SESSION['rndSeed'].')', 'limit' => '10'));
...