Представьте, что у вас есть большое количество записей в базе данных XML на основе XQuery:
<widgets>
<widget id="1" name="Foo Widget" price="19.99" />
<widget id="2" name="Bar Widget" price="29.99" />
<widget id="3" name="Baz Widget" price="39.99" />
<!-- etc. -->
</widget>
Под «большим числом» я подразумеваю миллион или больше.
Вы хотите получить один элемент из списка случайным образом, используя XQuery:
let $widgets := for $widget in //widgets/widget
order by util:random()
return $widget
for $val in subsequence($widgets, 1, 1)
return $val
Когда количество записей растет, выполнение оценки занимает слишком много времени, так как кажется, что загружается все из базы данных и переупорядочивается в памяти. Я думаю, что это может быть O(n log 2n). Медлительность, вызывающая вздох.
Есть ли более ленивый и лучший способ сделать это?
Есть метод «подсчитать количество элементов, затем случайным образом выбрать число от нуля для подсчета», которого я бы предпочел избежать.
В идеале база данных могла бы это сделать, если бы была какая-то фича типа:
let $widgets := for $widget in //widgets/widget
order by util:random()
limit 1
return $widget
Думаю, это будет FLOLWR. Но этого нет в спецификации XQuery, хотя это достаточно распространенная вещь, которую можно сделать в SQL (или даже в SPARQL или ряде других языков запросов).
Есть ли способ получить это? Добавление предложения where сделает это, но предложения where оцениваются до предложений порядка, что на самом деле не помогает.
Какие-либо предложения? (Приложение, отправляющее XQueries, написано на Java, а база данных XML — это eXist, если это поможет с какими-то немного более кривыми, нестандартными идеями.)