Запросы для случайных записей N на хранилище данных Appengine

Какой язык? и почему использование regex для этой простой задачи?

, Если Вы должны :

^(.*)/([^/]*)$

дает Вам эти две части, которые Вы хотели. Вы, возможно, должны были бы заключить круглые скобки в кавычки:

^\(.*\)/\([^/]*\)$

в зависимости от Вашего предпочтительного синтаксиса языка.

, Но я предлагаю, чтобы Вы просто использовали функцию поиска строки своего языка, которая находит последнее "/" символ и разделяет строку на том индексе.

9
задан David Underhill 21 July 2010 в 09:01
поделиться

5 ответов

«Под капотом» один вызов поискового запроса может вернуть только набор последовательных строк из некоторого индекса. Вот почему некоторые запросы GQL, включая любое использование! =, Расширяются до нескольких вызовов хранилища данных.

N независимых однородных случайных выборок (как правило) не являются последовательными ни в одном индексе.

QED.

Вы, вероятно, могли бы использовать memcache для хранения сущностей и уменьшить стоимость захвата N из них. Или, если вы не возражаете, чтобы «случайные» выборки были близко друг к другу в индексе, выберите случайно выбранный блок из (скажем) 100 в одном запросе, а затем выберите N случайным образом из них. Поскольку у вас есть поле, которое уже рандомизировано, для постороннего не сразу будет очевидно, что N элементов связаны. По крайней мере, до тех пор, пока они не посмотрят на множество выборок и не заметят, что элементы A и Z никогда не появляются в одной и той же группе, потому что в рандомизированном индексе их разделяет более 100. А если позволяет производительность, вы можете время от времени повторно рандомизировать свои сущности.

выборки близки друг к другу в индексе, выберите случайно выбранный блок из (скажем) 100 в одном запросе, затем выберите N случайным образом из них. Поскольку у вас есть поле, которое уже рандомизировано, для постороннего не сразу будет очевидно, что N элементов связаны. По крайней мере, до тех пор, пока они не посмотрят на множество выборок и не заметят, что элементы A и Z никогда не появляются в одной и той же группе, потому что в рандомизированном индексе их разделяет более 100. А если позволяет производительность, вы можете время от времени повторно рандомизировать свои сущности.

выборки близки друг к другу в индексе, выберите случайно выбранный блок из (скажем) 100 в одном запросе, затем выберите N случайным образом из них. Поскольку у вас есть поле, которое уже рандомизировано, для постороннего не сразу будет очевидно, что N элементов связаны. По крайней мере, до тех пор, пока они не посмотрят на множество выборок и не заметят, что элементы A и Z никогда не появляются в одной и той же группе, потому что в рандомизированном индексе их разделяет более 100. А если позволяет производительность, вы можете время от времени повторно рандомизировать свои сущности.

только после того, как они посмотрят на множество выборок и не заметят, что элементы A и Z никогда не появляются в одной и той же группе, потому что они более чем на 100 различаются в рандомизированном индексе. А если позволяет производительность, вы можете время от времени повторно рандомизировать свои сущности.

только после того, как они посмотрят на множество выборок и не заметят, что элементы A и Z никогда не появляются в одной и той же группе, потому что они более чем на 100 различаются в рандомизированном индексе. А если позволяет производительность, вы можете время от времени повторно рандомизировать свои сущности.

5
ответ дан 2 November 2019 в 23:09
поделиться

Какие компромиссы вы ищете? Если вы готовы смириться с небольшим снижением производительности при вставке этих сущностей, вы можете создать решение, чтобы очень быстро получить N из них.

Вот что вам нужно сделать:

Когда вы вставляете свои сущности, укажите ключ. Вы хотите расположить ключи к своим сущностям по порядку, начиная с 1 и далее вверх. (Это потребует некоторых усилий, поскольку движок приложения не имеет autoincrement (), поэтому вам нужно будет отслеживать последний идентификатор, который вы использовали в каком-то другом объекте, назовем его IdGenerator)

Теперь, когда вам нужно N случайные сущности, сгенерируйте N случайных чисел от 1 до любого сгенерированного вами последнего идентификатора (ваш IdGenerator будет это знать). Затем вы можете выполнить пакетное получение по ключу, используя N ключей, что потребует только одного посещения хранилища данных, и будет быстрее, чем запрос, так как получение ключей обычно происходит быстрее, чем запросы, AFAIK.

Этот метод действительно требует решения нескольких раздражающих деталей:

  1. Ваш IdGenerator может стать узким местом, если вы вставляете много эти элементы на лету (более нескольких секунд), что потребует какой-то сегментированной реализации IdGenerator. Если все эти данные предварительно загружены или не имеют большого объема, у вас это легко.
  2. Вы можете обнаружить, что с некоторым идентификатором больше не связана сущность, потому что вы его удалили или из-за сбоя метода put () где-то. Если бы это произошло, вам пришлось бы схватить другую случайную сущность. (Если вы хотите пофантазировать и уменьшить вероятность этого, вы можете сделать этот идентификатор доступным для IdGenerator для повторного использования, чтобы «заполнить пробелы»
5
ответ дан 2 November 2019 в 23:09
поделиться

Looks like the only method is by storing the random integer value in each entity's special property and querying on that. This can be done quite automatically if you just add an automatically initialized property.

Unfortunately this will require processing of all entities once if your datastore is already filled in.

It's weird, I know.

3
ответ дан 2 November 2019 в 23:09
поделиться

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

Это выбирает записи «count» из записей «totalcount», отсортированных по ключу .

    # select $count from the complete set
    numberlist = random.sample(range(0,totalcount),count)
    numberlist.sort()

    pagesize=1000

    #initbuckets
    buckets = [ [] for i in xrange(int(max(numberlist)/pagesize)+1) ]
    for k in numberlist:
        thisb = int(k/pagesize)
        buckets[thisb].append(k-(thisb*pagesize))
    logging.debug("Numbers: %s. Buckets %s",numberlist,buckets)

    #page through results.

    result = []
    baseq =  db.Query(MyEntries,keys_only=True).order("__key__")
    for b,l in enumerate(buckets):
        if len(l) > 0: 
            result += [ wq.fetch(limit=1,offset=e)[0] for e in l ]

        if b < len(buckets)-1: # not the last bucket
            lastkey  = wq.fetch(1,pagesize-1)[0]
            wq = baseq.filter("__key__ >",lastkey)

Помните, что для меня это несколько сложно, и я до сих пор не уверен, что у меня нет единичных или некорректных ошибок.

И будьте осторожны, если число близко к totalcount это может быть очень дорого. И имейте в виду, что с миллионами строк это может быть невозможно в рамках временных границ appengine.

0
ответ дан 2 November 2019 в 23:09
поделиться

Я согласен с ответом Стива, такого способа получения N случайных строк в одном запросе нет.

Однако даже метод получения одной единственной сущности, как правило, не работает таким образом, чтобы орбиты возвращаемых результатов были равномерно распределены. Вероятность возврата данной сущности зависит от разрыва случайно присвоенного ей числа и следующего более высокого случайного числа. Например, если случайным числам 1,2 и 10 были присвоены (и ни одно из чисел 3-9), алгоритм вернет "2" в 8 раз чаще, чем "1".

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

.
1
ответ дан 2 November 2019 в 23:09
поделиться
Другие вопросы по тегам:

Похожие вопросы: