Объединить триграмму с ранжированным поиском в джанго 1.10

Мы работаем с поиском в django 1.10, и нам нужен поиск по ранжированию с поиском триграмм.

Наш код таков:

def get_queryset(self):
        search = self.request.GET.get('text', '')
        vector = SearchVector('name',weight='A',
            config=settings.SEARCH_LANGS[
                settings.LANGUAGE
            ],
            ) + SearchVector(
            'content',
            weight='B',
            config=settings.SEARCH_LANGS[
                settings.LANGUAGE
            ],
            )
        query = SearchQuery(search)
        return Article.objects.annotate(
            rank=SearchRank(
                vector,
                query
                ),
            similarity=TrigramSimilarity(
                'name', search
                ) + TrigramSimilarity(
                'content', search
                ),
            ).filter(
            rank__gte=0.3
            ).filter(
            similarity__gt=0.3
            ).order_by(
            '-similarity'
            )[:20]

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

Как мы можем комбинировать триграмму и ранжированный поиск в django 1.10?

Ответ 1

Мы исследовали более тщательно поняли, как работает поиск весов.

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

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

Немного логики говорит нам, что если мы ищем общее слово во всех, все мы будем иметь ранг 0, сходство варьируется гораздо больше, чем диапазоны, однако имеет тенденцию к снижению значений этого диапазона.

Теперь текстовый поиск, насколько мы понимаем, осуществляется на основе текста, содержащегося в полях, которые вы хотите отфильтровать даже больше, чем на языке, который помещен в конфигурацию. Примером является то, что при размещении заголовков использованная модель имела поле заголовка и поле контента, наиболее распространенными словами которого были how change: просмотр взвешенных слов (диапазоны функционируют как запрос, поэтому мы можем использовать values или values_list для просмотра рангов и сходств (которые являются числовыми значениями, мы можем просматривать взвешенные слова, просматривая векторный объект), мы увидели, что, если веса были распределены, но комбинации разделенных слов: найдены 'perfil' и 'cambi', однако мы не нашли 'cambiar' или 'como "; однако все модели содержали один и тот же текст как "lorem ipsun..." и все слова этого предложения, если они были целыми и с весами B; На этом мы заключаем, что поиск выполняется на основе содержимого полей, чтобы фильтровать больше, чем язык, на котором мы настраиваем поиск.

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

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

from __future__ import unicode_literals

from django.db import migrations, models
import django.db.models.deletion
from django.contrib.postgres.operations import UnaccentExtension
from django.contrib.postgres.operations import TrigramExtension

class Migration(migrations.Migration):

    initial = True

    dependencies = [
    ]

    operations = [
      ...
      TrigramExtension(),
      UnaccentExtension(),

    ]

Импортируйте операции для миграции из пакетов postgres и запускайте из любой миграции файлов.

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

def get_queryset(self):
        search_query = SearchQuery(self.request.GET.get('q', ''))

        vector = SearchVector(
            'name',
            weight='A',
            config=settings.SEARCH_LANGS[settings.LANGUAGE_CODE],
        ) + SearchVector(
            'content',
            weight='B',
            config=settings.SEARCH_LANGS[settings.LANGUAGE_CODE],
        )

        if self.request.user.is_authenticated:
            queryset = Article.actives.all()
        else:
            queryset = Article.publics.all()

        return queryset.annotate(
          rank=SearchRank(vector, search_query)
          similarity=TrigramSimilarity(
              'name', search_query
            ) + TrigramSimilarity(
              'content', search_query
            ),
        ).filter(Q(rank__gte=0.3) | Q(similarity__gt=0.3)).order_by('-rank')[:20]

Проблема с вышеприведенным кодом заключалась в том, что один запрос за другим просачивался, и если выбранное слово не появилось ни в одном из двух поисков, проблема больше. Мы используем объект Q для фильтрации с использованием соединителя OR, так что если один из двух не возвращает желаемого значения, отправьте другой на место.

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

Ответ 2

Какой каталог используется для этих миграций?