Как ускорить запросы mongoengine

Если у меня есть два объекта, как:

class User(Document):
    name = StringField()
    following = ListField(ReferenceField('User'))
    meta = {
        'indexes': [
            'following',
        ]
    }

class Media(Document):
    owner = ReferenceField('User')
    url = StringField()
    is_hidden = BooleanField()
    posted_date = Date

    meta = {
        'indexes': [
            'owner',
            'posted_date',
            'is_hidden',
        ]
    }

и когда я хочу найти следующее условие, когда оно не скрыто, и его владельцем является тот, за кем я следую, и он был недавно опубликован, у меня появляется запрос, подобный этому:

user = User.objects.first()
Media.objects(Q(owner__in=user.following) &
              Q(is_hidden=False) &
              Q(posted_date__gte=dt.now()-dt.timedelta(days=3))

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

2 ответа

Решение

1) Использование User.objects.get(id=user_id) вместо first(), Хотя я не совсем уверен, если это будет иметь значение, я думаю, что да, и это find операция, при которой MongoDB возвращает курсор, а mongoengine выполняет итерацию к первому документу. Вместо, get() делает findOne и возвращает только 1 документ. Если я ошибаюсь, кто-то должен исправить меня, пожалуйста.

2) Используйте составной индекс (не несколько отдельных индексов), так как ваш запрос использует несколько полей (пример здесь также):

 meta = {
            'indexes': [
                ('owner', 'posted_date', 'is_hidden',)
            ]
        }

3) Ограничьте возврат данных только в те поля, которые вам нужны, спроецируйте ваши поля, используя only()

Используйте объяснение () в вашем запросе, чтобы изучить его и улучшить его в oder, чтобы достичь покрытого запроса.

Если вы планируете использовать mongoengine в производстве с большими документами, взгляните на этот пост: https://github.com/MongoEngine/mongoengine/issues/1230

Мы использовали mongoengine, но он стал очень медленным по причине, описанной в посте выше.

В итоге мы переписали весь наш бэкэнд, используя https://github.com/mongodb/pymodm Это относительно новый проект для команды mongodb. Мы используем его с Django, и он работает намного быстрее, чем mongoengine с точно такой же базой данных.

Другие вопросы по тегам