Получение случайной записи от объекта Objectify

Как получить случайный элемент из хранилища данных Google App Engine с помощью Objectify? Должен ли я получить все ключи сущности и выбрать из них случайным образом или есть лучший способ?


person Ben Flynn    schedule 31.10.2011    source источник


Ответы (4)


Назначьте случайное число от 0 до 1 каждому объекту при его сохранении. Чтобы получить случайную запись, сгенерируйте другое случайное число от 0 до 1 и запросите наименьший объект со случайным значением больше этого.

person Nick Johnson    schedule 31.10.2011
comment
Неплохая идея, хотя кажется, что я буду создавать индекс исключительно для выбора данных, что кажется неудачным. Моя таблица будет обновляться нечасто, поэтому я думаю о локальном кэшировании списка ключей, а затем случайном захвате (избегая дополнительного столбца/индекса/запроса). - person Ben Flynn; 01.11.2011

Вам не нужно получать все. Например:

  1. countall = query(X.class).count() // http://groups.google.com/group/objectify-appengine/browse_frm/thread/3678cf34bb15d34d/82298e615691d6c5?lnk=gst&q=count#82298e615691d6c5
  2. rnd = Генерировать случайное число [0..countall]
  3. ofy.query(X.class).order("- date").limit(rnd); //например -дата или какое-то хроническое индексированное поле
  4. Последний идентификатор - это ваш ... (в среднем вы поймали 50% или, по крайней мере, первое чтение в среднем на 50% меньше)

Улучшения (чтобы иметь меньшую таблицу ключей в кеше)!

После первого прочтения запомните все X элементов. Кэшировать идентификаторы и их положение. Таким образом, в следующий раз запросите условие из выбранного идентификатора (макс. «.limit (rnd% X)» будет X-1).

Случайный — это просто случайный, если он не должен быть близок к 100%, укажите постоянное значение поля (например, если у вас есть 1000 записей за 10 дней, для случайного 501 выберите второй элемент больше, чем пятый день).

Другие варианты, если у вас есть хроническая дата поля (или аналогичная), извлекайте элементы старше, чем случайная дата, и моложе, чем случайная дата + 1 (вам нужно знать первую дату и последнюю дату). Во-вторых, выберите случайный выбор между выбранными записями. Если запрос пуст, выберите больше, чем и т.д....

person MatejC    schedule 12.11.2011

Цитата из этот пост о выборе случайных элементы из хранилища данных Objectified:

Если ваши идентификаторы являются последовательными, одним из способов будет случайный выбор 5 номеров из диапазона идентификаторов, которые, как известно, используются. Затем используйте запрос с фильтром "in"().

Если вы не возражаете против того, чтобы 5 записей были соседними, вы можете использовать count(), limit() и offset(), чтобы случайным образом найти блок из 5 записей.

В противном случае вам, вероятно, придется использовать limit() и offset() для случайного выбора одной записи за раз.

-- Джош

person Steven Roose    schedule 06.02.2013

Я в значительной степени адаптирую алгоритм, предоставленный Matejc. Тем не менее, 3 вещи:

  1. Вместо использования count() или фабрики служб хранилища данных (DatastoreServiceFactory.getDatastoreService()) у меня есть сущность, которая отслеживает общее количество интересующих меня сущностей. Причина такого подхода заключается в следующем: a. count() может быть дорогим, когда вы имеете дело с большим количеством объектов b. Вы не можете протестировать фабрику сервисов хранилища данных локально... тестирование в рабочей среде — это просто плохая практика.

  2. Генерация случайного числа: ThreadLocalRandom.current().nextLong(1, maxRange)

  3. Вместо использования limit() я использую смещение, поэтому мне не нужно беспокоиться о «сортировке».

person Johnny Wu    schedule 31.10.2017