Django - отфильтровать по БД или вычислить в Python - PullRequest
0 голосов
/ 21 декабря 2018

Предположим, теперь у меня есть 2 модели, A и B.

И между A и B существует отношение многие ко многим

class B(models.Model):
    score_b = model.IntegerField()

class A(models.Model):
    b = models.ManyToMany(B, related_name='b_set')
    score_a = models.IntegerField()
    name = models.CharField(unique=True)

==

Рабочий процесс - сначала я фильтрую некоторый экземпляр A по score_a и использую их для запроса B с score_b

Так что наивный фрагмент кода может выглядеть так (Решение A)

## Solution A

stuff = {}

a_list = A.objects.filter(score_a__gte=100)
for a in a_list:
    qs = a.b_set.filter(score_b__gte=200)
    stuff[a.name] = [b.score for b in qs]

return stuff

Но я стараюсь изо всех сил улучшить производительность

И предыдущий код, похоже, требует 1 + len(a_list) доступ к базе данных

Так что я бы попробовал использовать prefetch_related (Решение B)

## Solution B

stuff = {}

a_list = A.objects.filter(score_a__gte=100).prefetch_related('b')
for a in a_list:
    qs = a.b_set.filter(score_b__gte=200)
    stuff[a.name] = [b.score for b in qs]

return stuff

Однако кажется, что кэшированный b будет игнорироваться, поскольку filter - это другой запрос.Таким образом, приведенный выше код не помогает вообще.

Теперь ему требуется 1 + 1 + len(a_list) доступ к базе данных из-за дополнительного prefetch_related запроса

Теперь я придумаю еще одну идею - фильтр b вpython для уменьшения доступа к базе данных (Решение C)

## Solution C

stuff = {}

a_list = A.objects.filter(score_a__gte=100).prefetch_related('b')
for a in a_list:
    qs = a.b_set.all()
    temp = [b.score for b in qs if b.score >= 200]
    stuff[a.name] = temp
return stuff

И теперь количество обращений к базе данных должно упасть до 1, что является удивительным

Но я беспокоюсь о выполнении фильтрав python может быть намного медленнее, чем фильтр в базе данных

Будет ли он работать в Solution C быстрее, чем Solution A?

Спасибо!

Edit

Я отредактировал фрагмент кода.

Извините за мой плохой английский и плохое описание, которые приводят к недоразумению.

Мой вопрос о том, должен ли я всегда выполнять фильтрацию в базе данных или это нормально делатьэто в Python, особенно когда последний может сохранить некоторые / многие доступ к базе данных.

1 Ответ

0 голосов
/ 21 декабря 2018

Это должно быть возможно с одним запросом БД через ORM:

b_list = B.objects.filter(b_score__gte=200, a__score_a__gte=100).distinct()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...