Выберите случайные данные с DataMapper

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

Например, у меня есть набор данных:

+-------------------+
| ID | Name | Value |
+-------------------+
| 1  | T1   | 123   |
| 2  | T2   | 456   |
| 3  | T3   | 789   |
| 4  | T4   | 101   |
| ----------------- |
| N  | Tn   | value |

Данных может быть много, более 100 тыс. строк.

И мне нужно сопоставить данные с объектом:

class Item
  include DataMapper::Resource
  property :id, Serial
  property :name, String
  property :value, String
end

Итак, вопрос: как выбрать случайные данные из таблицы?

Аналогичный запрос в SQL будет:

SELECT id, name, value FROM table ORDER BY RAND() LIMIT n;

person Dan Sosedoff    schedule 12.06.2009    source источник


Ответы (3)


Вы можете сгенерировать случайное число x ‹ number_of_rows и просто получить этот идентификатор.

Вы также можете попробовать ввести SQL напрямую, например:

find_by_sql(<<-SQL
    SELECT `id`, `name`, `value` FROM table ORDER BY RAND() LIMIT n;
SQL, :properties => property_set)

Однако вам нужно указать :properties, чтобы он сопоставлялся с вашим набором свойств.

person cloudhead    schedule 12.06.2009
comment
Но что, если у меня есть такая последовательность идентификаторов: 1, 3300, 91928, 234? И меня больше интересует, как получить набор данных, а не только отдельные строки. - person Dan Sosedoff; 12.06.2009
comment
Обновил ответ другим решением - person cloudhead; 12.06.2009

Спустя долгое время после OP, но поскольку это первый поиск в Google для «случайной строки datamapper»...

Используя чистый DataMapper и не делая предположений о непрерывных идентификаторах и т. д., вы можете сделать:

Item.first(:offset => rand(Item.count))

что приводит к запросам:

SELECT COUNT(*) FROM `items`
SELECT <fields> FROM `items` ORDER BY `id` LIMIT 1 OFFSET <n>

Если вы предпочитаете один запрос за счет потенциального снижения скорости, вы можете сделать следующее:

Item.all.sample

в то время как результаты:

SELECT <fields> FROM `items` ORDER BY `id`

Очевидно, оберните это в транзакцию, если вам нужно.

person canton7    schedule 29.01.2012

Обычно меня не волнует буквальное извлечение случайных записей. В этом случае я использую немного другую парадигму.

  1. ORDER BY value // или value mod некоторое число // вы также можете использовать имя или какую-либо функцию для имени
  2. ВЫБЕРИТЕ ПРЕДЕЛ n СМЕЩЕНИЕ k

где k — случайное число, сгенерированное в вашем коде меньше, чем N-n. Достаточно случайный для большинства случаев, даже если записи несколько непрерывны в том, что вы используете для ORDER BY.

person Ryan Oberoi    schedule 12.06.2009