В моем приложении Django есть модель Item
с полем ManyToMany, которое обрабатывается с помощью промежуточной модели избранного. Вот упрощенные версии рассматриваемых моделей:
class Item(models.Model):
name = models.CharField(max_length=200)
class Favorite(models.Model):
user = models.ForeignKey(User)
item = models.ForeignKey(Item)
Я пытаюсь получить список предметов, упорядоченных по количеству избранных. Приведенный ниже запрос работает, однако в таблице Item есть тысячи записей, и выполнение запроса может занять до нескольких минут.
items = Item.objects.annotate(num_favorites=Count('favorite')).order_by('-num_favorites')
Не уверен, относится ли это к каким-либо потенциальным ответам, но я разбиваю результаты на страницы, используя встроенный в Django Pagintor:
paginator = Paginator(items, 100)
Я знаю, что могу добавить поле favorites
к своей модели Предмета и увеличивать его каждый раз, когда предмет добавляется в список предпочтений, но мне интересно, есть ли другой более чистый, более эффективный способ получения этих данных в разумные сроки.
Ниже приведен вывод функции MySQL EXPLAIN
:
+----+-------------+--------------------+------+-----------------------------+-----------------------------+---------+-------------------------------+------+---------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------------------+------+-----------------------------+-----------------------------+---------+-------------------------------+------+---------------------------------+
| 1 | SIMPLE | appname_item | ALL | NULL | NULL | NULL | NULL | 566 | Using temporary; Using filesort |
| 1 | SIMPLE | appname_favorite | ref | appname_favorite_67b70d25 | appname_favorite_67b70d25 | 4 | appname.appname_item.id | 1 | |
+----+-------------+--------------------+------+-----------------------------+-----------------------------+---------+-------------------------------+------+---------------------------------+