Существует множество способов выбора случайного документа из коллекции mongodb (как обсуждалось в этом ответе). Комментарии указывают, что с версией mongodb >= 3.2, тогда использование $sample
в структуре агрегации является предпочтительным. Однако в коллекции со многими небольшими документами это кажется чрезвычайно медленным.
В следующем коде используется mongoengine для имитации проблемы и сравнения ее с методом "skip random":
import timeit
from random import randint
import mongoengine as mdb
mdb.connect("test-agg")
class ACollection(mdb.Document):
name = mdb.StringField(unique=True)
meta = {'indexes': ['name']}
ACollection.drop_collection()
ACollection.objects.insert([ACollection(name="Document {}".format(n)) for n in range(50000)])
def agg():
doc = list(ACollection.objects.aggregate({"$sample": {'size': 1}}))[0]
print(doc['name'])
def skip_random():
n = ACollection.objects.count()
doc = ACollection.objects.skip(randint(1, n)).limit(1)[0]
print(doc['name'])
if __name__ == '__main__':
print("agg took {:2.2f}s".format(timeit.timeit(agg, number=1)))
print("skip_random took {:2.2f}s".format(timeit.timeit(skip_random, number=1)))
Результат:
Document 44551
agg took 21.89s
Document 25800
skip_random took 0.01s
В прошлом, когда у меня были проблемы с производительностью с mongodb, мой ответ всегда заключался в использовании структуры агрегации, поэтому я удивлен, что $sample
работает так медленно.
Я что-то упустил? Что это за пример, который вызывает агрегацию так долго?