PostgreSQL текстовый поиск в Django не работает должным образом - PullRequest
1 голос
/ 27 апреля 2020

Я реализую функцию поиска для моего API, чтобы при запросе возвращать свойства объекта. До сих пор я пытался использовать Полнотекстовый поиск , который можно использовать, но он имеет следующие раздражающие вещи: слова должны быть написаны правильно, чтобы результаты были возвращены, и частичный поиск, например, «appl» вместо « яблоко ", не сработает. Я также попробовал Trigram Similarity , но он не удался для длинных предложений. Как реализовать функцию поиска, которая является одновременно точной и нечеткой в ​​Django?

Это работает

enter image description here

Это не сработает

enter image description here enter image description here

Это мой views.py

from django.shortcuts import render
from rest_framework.response import Response
from rest_framework import status
from rest_framework.decorators import api_view
from .models import Object_Locations
from .serializers import Object_LocationsSerializer
from django.contrib.postgres.search import SearchVector, SearchQuery


def index(request):
   return render(request, 'main/base.html', {})

@api_view(['GET',])
def LocationsList(request):
    if request.method == 'GET':
        vector = SearchVector('name', 'desc', 'catergory')
        query = request.GET.get('search')

        if query:
            locations = Object_Locations.objects.annotate(search=vector,).filter(search=SearchQuery(query))
        else:
            locations = Object_Locations.objects.all()

        serializer = Object_LocationsSerializer(locations, many=True)
        return Response(serializer.data)

1 Ответ

2 голосов
/ 27 апреля 2020

Из документации SearchQuery :

SearchQuery переводит термины, предоставленные пользователем, в объект поискового запроса, который база данных сравнивается с вектором поиска. По умолчанию все слова, которые предоставляет пользователь, передаются через алгоритмы стемминга, а затем он ищет совпадения для всех полученных терминов.

Если search_type равен 'plain' , который используется по умолчанию, термины рассматриваются как отдельные ключевые слова. Если search_type равен 'фразу' , термины рассматриваются как одна фраза. Если search_type равен 'raw' , вы можете предоставить отформатированный поисковый запрос с терминами и операторами.

В коде выше SearchQuery с поисковой фразой "бла c лайка" переводится в SQL код, например:

... @@ plainto_tsquery('a blac husky') ...

Так что если вы хотите получать результаты с похожим поиском фразы, которые можно объединить с условиями запроса:

from django.contrib.postgres.search import SearchQuery, SearchVector
from django.shortcuts import render
from rest_framework import status
from rest_framework.decorators import api_view
from rest_framework.response import Response

from .models import Object_Locations
from .serializers import Object_LocationsSerializer


def index(request):
return render(request, 'main/base.html', {})


@api_view(['GET',])
def LocationsList(request):
    if request.method == 'GET':
        vector = SearchVector('name', 'desc', 'catergory')
        query_terms = request.GET.get('search')
        query_raw = ' | '.join(query_terms.split())
        query = SearchQuery(query_raw, search_type='raw')
        if query.value:
            locations = Object_Locations.objects.annotate(search=vector).filter(search=query)
        else:
            locations = Object_Locations.objects.all()
        serializer = Object_LocationsSerializer(locations, many=True)
        return Response(serializer.data)

В приведенном выше коде SearchQuery с поисковой фразой "бла c лайка" переводится на SQL код типа:

... @@ plainto_tsquery('a | blac | husky') ...

Можно использовать логическую операцию для объединения SearchQuery, как описано в документации, которую я связал.

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

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

...