Django objects.filter, насколько "дорогой" это будет? - PullRequest
1 голос
/ 21 декабря 2008

Я пытаюсь сделать поиск в Джанго. Это форма поиска с вводом свободного текста + некоторыми опциями для выбора, так что вы можете фильтровать по годам и так далее. Это часть кода, который я имею в виду, часть, которая выполняет фильтрацию. И я хотел бы получить информацию о том, как дорого это будет на сервере базы данных.

soknad_list = Soknad.objects.all()</p> <pre><code>if var1: soknad_list = soknad_list.filter(pub_date__year=var1) if var2: soknad_list = soknad_list.filter(muncipality__name__exact=var2) if var3: soknad_list = soknad_list.filter(genre__name__exact=var3) # TEXT SEARCH stop_word_list = re.compile(STOP_WORDS, re.IGNORECASE) search_term = '%s' % request.GET['q'] cleaned_search_term = stop_word_list.sub('', search_term) cleaned_search_term = cleaned_search_term.strip() if len(cleaned_search_term) != 0: soknad_list = soknad_list.filter(Q(dream__icontains=cleaned_search_term) | Q(tags__icontains=cleaned_search_term) | Q(name__icontains=cleaned_search_term) | Q(school__name__icontains=cleaned_search_term))

Итак, сначала я делаю список всех объектов, затем проверяю, какие переменные существуют (я получаю их с помощью GET в более ранней точке), а затем фильтрую результаты, если они существуют. Но это не кажется слишком элегантным, оно, вероятно, выполняет много запросов для достижения результата, так есть ли лучший способ для этого?

Это именно то, что я хочу, но я думаю, что есть лучший / умный способ сделать это. Есть идеи?

Ответы [ 3 ]

4 голосов
/ 21 декабря 2008
Фильтр

сам не выполняет запрос, запрос не выполняется до тех пор, пока вы явно не выберете элементы из запроса (например, get), и список (запрос) также не выполнит его.

2 голосов
/ 21 декабря 2008

Вы можете увидеть запрос, который будет сгенерирован с помощью:

soknad_list.query.as_sql()[0]

Затем вы можете поместить это в оболочку базы данных, чтобы узнать, сколько времени занимает запрос, или использовать EXPLAIN (если это поддерживает ваша база данных), чтобы узнать, насколько это дорого.

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

Как уже упоминал Аарон, вы должны взять текст запроса, который будет выполняться в базе данных, и использовать EXPLAIN (или другой метод) для просмотра плана выполнения запроса. Как только вы получите план выполнения запроса, вы сможете увидеть, что происходит в самой базе данных. Существует множество операций, выполнение которых обходится через процедурный код очень дорого, что очень просто для любой базы данных, особенно если вы предоставляете индексы, которые база данных может использовать для ускорения вашего запроса.

Если я правильно прочитал ваш вопрос, вы получаете набор результатов всех строк в таблице Soknad. Получив эти результаты обратно, вы используете метод filter (), чтобы урезать результаты в соответствии с вашими критериями. Если посмотреть на документацию по Django, похоже, что он будет выполнять фильтрацию в памяти, а не повторно запрашивать базу данных (конечно, это действительно зависит от того, какой слой доступа к данным вы используете, а не от самого Django).

Наиболее оптимальным решением было бы использование полнотекстового поискового движка (Lucene, ferret и т. Д.), Чтобы справиться с этим для вас. Если это недоступно или нецелесообразно, следующим лучшим вариантом будет создание предиката запроса (предложение WHERE) перед отправкой запроса в базу данных и позволить базе данных выполнить фильтрацию.

Однако, , как и во всех вещах, связанных с базой данных, реальный ответ - «это зависит». Лучшее предложение - опробовать несколько различных подходов с использованием данных, близких к производственным, и сравнить их как минимум за 3 итерации, прежде чем приступать к окончательному решению проблемы. Может быть так же быстро или даже быстрее фильтровать в памяти, а не фильтровать в базе данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...