Как получить случайный элемент из хранилища данных Google App Engine с помощью Objectify? Должен ли я получить все ключи сущности и выбрать из них случайным образом или есть лучший способ?
Получение случайной записи от объекта Objectify
Ответы (4)
Назначьте случайное число от 0 до 1 каждому объекту при его сохранении. Чтобы получить случайную запись, сгенерируйте другое случайное число от 0 до 1 и запросите наименьший объект со случайным значением больше этого.
Вам не нужно получать все. Например:
- countall = query(X.class).count() // http://groups.google.com/group/objectify-appengine/browse_frm/thread/3678cf34bb15d34d/82298e615691d6c5?lnk=gst&q=count#82298e615691d6c5
- rnd = Генерировать случайное число [0..countall]
- ofy.query(X.class).order("- date").limit(rnd); //например -дата или какое-то хроническое индексированное поле
- Последний идентификатор - это ваш ... (в среднем вы поймали 50% или, по крайней мере, первое чтение в среднем на 50% меньше)
Улучшения (чтобы иметь меньшую таблицу ключей в кеше)!
После первого прочтения запомните все X элементов. Кэшировать идентификаторы и их положение. Таким образом, в следующий раз запросите условие из выбранного идентификатора (макс. «.limit (rnd% X)» будет X-1).
Случайный — это просто случайный, если он не должен быть близок к 100%, укажите постоянное значение поля (например, если у вас есть 1000 записей за 10 дней, для случайного 501 выберите второй элемент больше, чем пятый день).
Другие варианты, если у вас есть хроническая дата поля (или аналогичная), извлекайте элементы старше, чем случайная дата, и моложе, чем случайная дата + 1 (вам нужно знать первую дату и последнюю дату). Во-вторых, выберите случайный выбор между выбранными записями. Если запрос пуст, выберите больше, чем и т.д....
Цитата из этот пост о выборе случайных элементы из хранилища данных Objectified:
Если ваши идентификаторы являются последовательными, одним из способов будет случайный выбор 5 номеров из диапазона идентификаторов, которые, как известно, используются. Затем используйте запрос с фильтром "in"().
Если вы не возражаете против того, чтобы 5 записей были соседними, вы можете использовать count(), limit() и offset(), чтобы случайным образом найти блок из 5 записей.
В противном случае вам, вероятно, придется использовать limit() и offset() для случайного выбора одной записи за раз.
-- Джош
Я в значительной степени адаптирую алгоритм, предоставленный Matejc. Тем не менее, 3 вещи:
Вместо использования count() или фабрики служб хранилища данных (DatastoreServiceFactory.getDatastoreService()) у меня есть сущность, которая отслеживает общее количество интересующих меня сущностей. Причина такого подхода заключается в следующем: a. count() может быть дорогим, когда вы имеете дело с большим количеством объектов b. Вы не можете протестировать фабрику сервисов хранилища данных локально... тестирование в рабочей среде — это просто плохая практика.
Генерация случайного числа: ThreadLocalRandom.current().nextLong(1, maxRange)
Вместо использования limit() я использую смещение, поэтому мне не нужно беспокоиться о «сортировке».