Низкая производительность, когда сходство триграмм и полнотекстовый поиск были объединены с Q ind django с использованием postgres - PullRequest
1 голос
/ 11 июня 2019

Я создаю веб-приложение для поиска людей по их свойствам, таким как образование, опыт и т. Д. Я не могу использовать полнотекстовый поиск по всем полям, потому что некоторые из них должны быть нечеткими. (Например: если мы ищем биотехнологию, она должна выбрать биотехнологию, биотехнологию, а также биотехнологию). Моя база данных содержит около 200 записей в модели профиля, которая должна отображаться в результатах поиска.

Другие модели, такие как образование и опыт, связаны с профилем через внешний ключ

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

Однако, поскольку я должен сделать это в нескольких полях, я использовал простой поиск вместо использования векторов поиска.

Profile.objects.filter(
    Q(first_name__trigram_similar=search_term) |
    Q(last_name__trigram_similar=search_term) |
    Q(vision_expertise__search=search_term) |
    Q(educations__degree__trigram_similar=search_term) |
    Q(educations__field_of_study__trigram_similar=search_term) |
    Q(educations__school__trigram_similar=search_term) |
    Q(educations__description__search=search_term) |
    Q(experiences__title__trigram_similar=search_term) |
    Q(experiences__company__trigram_similar=search_term) |
    Q(experiences__description__search=search_term) |
    Q(publications__title__trigram_similar=search_term) |
    Q(publications__description__search=search_term) |
    Q(certification__certification_name__trigram_similar=search_term) |
    Q(certification__certification_authority__trigram_similar=search_term) |
    Q(bio_description__search=search_term) |
)

Я получаю ожидаемые результаты при каждом поиске. Однако, время, которое требуется, чтобы получить это смехотворно медленно. Я не могу понять, как сделать это быстрее.

1 Ответ

1 голос
/ 11 июня 2019

Без кода класса трудно найти лучший способ оптимизировать ваш запрос.

Вы можете добавить индекс Gin или Gist , чтобы ускорить триграммуСходство.

Вы можете создать аннотацию с помощью SearchVector , как показано ниже:

from django.contrib.postgres.aggregates import StringAgg
from django.contrib.postgres.search import SearchQuery, SearchVector

search_vectors = (
    SearchVector('vision_expertise') +
    SearchVector('bio_description') +
    SearchVector(StringAgg('experiences__description', delimiter=' ')) +
    SearchVector(StringAgg('educations__description', delimiter=' ')) +
    SearchVector(StringAgg('publications__description', delimiter=' '))
)

Profile.objects.annotate(
    search=search_vectors
).filter(
    Q(search=SearchQuery(search_term)) |
    Q(first_name__trigram_similar=search_term) |
    Q(last_name__trigram_similar=search_term) |
    Q(educations__degree__trigram_similar=search_term) |
    Q(educations__field_of_study__trigram_similar=search_term) |
    Q(educations__school__trigram_similar=search_term) |
    Q(experiences__title__trigram_similar=search_term) |
    Q(experiences__company__trigram_similar=search_term) |
    Q(publications__title__trigram_similar=search_term) |
    Q(certification__certification_name__trigram_similar=search_term) |
    Q(certification__certification_authority__trigram_similar=search_term)
)

Вы можете ускорить полнотекстовый поиск с помощью SearchVectorField

Чтобы узнать о полнотекстовом поиске и триграмме, вы можете прочитать статью, которую я написал по этому вопросу:

"Полнотекстовый поиск в Django с PostgreSQL"

...