Spec-Zone.ru › Wagtail 3

Поиск

Поиск набора QuerySet

Поиск Wagtail основан на API QuerySet Django. Вы должны иметь возможность искать любой набор Django QuerySet, при условии, что модель и поля, по которым выполняется фильтрация, добавлены в индекс поиска.

Поиск страниц

Wagtail предоставляет сокращение для поиска страниц: метод .search() QuerySet. Вы можете вызвать его для любого PageQuerySet. Например:

# Search future EventPages
>>> from wagtail.models import EventPage
>>> EventPage.objects.filter(date__gt=timezone.now()).search("Hello world!")

Все другие методы PageQuerySet могут быть использованы с search(). Например:

# Search all live EventPages that are under the events index
>>> EventPage.objects.live().descendant_of(events_index).search("Event")
[<EventPage: Event 1>, <EventPage: Event 2>]

Примечание

Метод search() преобразует ваш QuerySet в экземпляр одного из классов SearchResults Wagtail (в зависимости от бэкэнда). Это означает, что вы должны выполнить фильтрацию перед вызовом search().

Примечание

До введения метода autocomplete(), метод поиска также выполнял частичное сопоставление. Это поведение будет устаревать, и вы должны либо переключиться на новый метод autocomplete(), либо передать partial_match=False в метод поиска, чтобы включить новое поведение. Частичное сопоставление в search() будет полностью удалено в будущей версии.

Автозаполнение поиска

Wagtail предоставляет отдельный метод, который выполняет частичное сопоставление со специфическими полями автозаполнения. Это полезно для предложений страниц пользователю в режиме реального времени по мере ввода запроса.

>>> EventPage.objects.live().autocomplete("Eve")
[<EventPage: Event 1>, <EventPage: Event 2>]

Подсказка

Этот метод следует использовать только для автозаполнения в реальном времени, а фактические запросы поиска всегда должны использовать метод search().

Поиск изображений, документов и пользовательских моделей

Модели документов и изображений Wagtail предоставляют метод search в своих QuerySet, как и страницы:

>>> from wagtail.images.models import Image

>>> Image.objects.filter(uploaded_by_user=user).search("Hello")
[<Image: Hello>, <Image: Hello world!>]

Пользовательские модели можно искать, используя метод search непосредственно в поисковом бэкенде:

>>> from myapp.models import Book
>>> from wagtail.search.backends import get_search_backend

# Search books
>>> s = get_search_backend()
>>> s.search("Great", Book)
[<Book: Great Expectations>, <Book: The Great Gatsby>]

Вы также можете передать QuerySet в метод search, что позволит вам добавить фильтры к результатам поиска:

>>> from myapp.models import Book
>>> from wagtail.search.backends import get_search_backend

# Search books
>>> s = get_search_backend()
>>> s.search("Great", Book.objects.filter(published_date__year__lt=1900))
[<Book: Great Expectations>]

Указание полей для поиска

По умолчанию Wagtail будет искать все поля, которые были проиндексированы с помощью index.SearchField.

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

# Search just the title field
>>> EventPage.objects.search("Event", fields=["title"])
[<EventPage: Event 1>, <EventPage: Event 2>]

Фильтрованный поиск

Wagtail поддерживает фильтрованный поиск, который представляет собой вид фильтрации на основе поля таксономии (такого как категория или тип страницы).

Метод .facet(field_name) возвращает OrderedDict. Ключи — это идентификаторы связанных объектов, на которые ссылается указанное поле, а значения — количество найденных ссылок для каждого идентификатора. Результаты упорядочены по количеству ссылок в порядке убывания.

Например, чтобы найти самые распространенные типы страниц в результатах поиска:

>>> Page.objects.search("Test").facet("content_type_id")

# Note: The keys correspond to the ID of a ContentType object; the values are the
# number of pages returned for that type
OrderedDict([
    ('2', 4),  # 4 pages have content_type_id == 2
    ('1', 2),  # 2 pages have content_type_id == 1
])

Изменение поведения поиска

Оператор поиска

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

  • “или” — результаты должны соответствовать хотя бы одному термину (по умолчанию для Elasticsearch)
  • “и” — результаты должны соответствовать всем терминам (по умолчанию для поиска в базе данных)

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

Мы рекомендуем использовать оператор «или» при упорядочении по релевантности и оператор «и» при упорядочении по чему-либо другому (прим.: бэкенд базы данных в настоящее время не поддерживает упорядочивание по релевантности).

Вот пример использования ключевого слова operator:

# The database contains a "Thing" model with the following items:
# - Hello world
# - Hello
# - World


# Search with the "or" operator
>>> s = get_search_backend()
>>> s.search("Hello world", Things, operator="or")

# All records returned as they all contain either "hello" or "world"
[<Thing: Hello World>, <Thing: Hello>, <Thing: World>]


# Search with the "and" operator
>>> s = get_search_backend()
>>> s.search("Hello world", Things, operator="and")

# Only "hello world" returned as that's the only item that contains both terms
[<Thing: Hello world>]

Для моделей страниц, изображений и документов ключевое слово operator также поддерживается в методе search QuerySet:

>>> Page.objects.search("Hello world", operator="or")

# All pages containing either "hello" or "world" are returned
[<Page: Hello World>, <Page: Hello>, <Page: World>]

Поиск фраз

Поиск фраз используется для поиска целых предложений или фраз, а не отдельных терминов. Термины должны появляться вместе и в том же порядке.

Например:

>>> from wagtail.search.query import Phrase

>>> Page.objects.search(Phrase("Hello world"))
[<Page: Hello World>]

>>> Page.objects.search(Phrase("World hello"))
[<Page: World Hello day>]

Если вы хотите реализовать запросы фраз с помощью синтаксиса двойных кавычек, см. Разбор строки запроса.

Сложные запросы поиска

С помощью классов запросов поиска Wagtail также поддерживает построение запросов поиска в виде Python-объектов, которые можно оборачивать и комбинировать с другими запросами поиска. Доступны следующие классы:

PlainText(query_string, operator=None, boost=1.0)

Этот класс оборачивает строку отдельных терминов. Это то же самое, что поиск без классов запросов.

Он принимает строку запроса, оператор и boost.

Например:

>>> from wagtail.search.query import PlainText
>>> Page.objects.search(PlainText("Hello world"))

# Multiple plain text queries can be combined. This example will match both "hello world" and "Hello earth"
>>> Page.objects.search(PlainText("Hello") & (PlainText("world") | PlainText("earth")))

Phrase(query_string)

Этот класс оборачивает строку, содержащую фразу. См. предыдущий раздел о том, как это работает.

Например:

# This example will match both the phrases "hello world" and "Hello earth"
>>> Page.objects.search(Phrase("Hello world") | Phrase("Hello earth"))

Boost(query, boost)

Этот класс повышает рейтинг другого запроса.

Например:

>>> from wagtail.search.query import PlainText, Boost

# This example will match both the phrases "hello world" and "Hello earth" but matches for "hello world" will be ranked higher
>>> Page.objects.search(Boost(Phrase("Hello world"), 10.0) | Phrase("Hello earth"))

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

Разбор строки запроса

Предыдущие разделы показывают, как вручную сконструировать запрос поиска фразы, но многие поисковые системы (включая административную панель Wagtail, попробуйте!) поддерживают написание запросов фраз путем обертывания фразы двойными кавычками. Кроме фраз, вы также можете разрешить пользователям добавлять фильтры в запрос с использованием синтаксиса двоеточия (hello world published:yes).

Эти две функции могут быть реализованы с помощью функции-утилиты parse_query_string. Эта функция принимает строку запроса, введенную пользователем, и возвращает объект запроса и словарь фильтров:

Например:

>>> from wagtail.search.utils import parse_query_string
>>> filters, query = parse_query_string('my query string "this is a phrase" this-is-a:filter', operator='and')

>>> filters
{
    'this-is-a': 'filter',
}

>>> query
And([
    PlainText("my query string", operator='and'),
    Phrase("this is a phrase"),
])

Вот пример использования этой функции в представлении поиска:

from wagtail.search.utils import parse_query_string

def search(request):
    query_string = request.GET['query']

    # Parse query
    filters, query = parse_query_string(query_string, operator='and')

    # Published filter
    # An example filter that accepts either `published:yes` or `published:no` and filters the pages accordingly
    published_filter = filters.get('published')
    published_filter = published_filter and published_filter.lower()
    if published_filter in ['yes', 'true']:
        pages = pages.filter(live=True)
    elif published_filter in ['no', 'false']:
        pages = pages.filter(live=False)

    # Search
    pages = pages.search(query)

    return render(request, 'search_results.html', {'pages': pages})

Настройка сортировки

По умолчанию результаты поиска упорядочены по релевантности, если бэкенд это поддерживает. Чтобы сохранить существующую сортировку QuerySet, ключевое слово order_by_relevance должно быть установлено в значение False в методе search().

Например:

# Get a list of events ordered by date
>>> EventPage.objects.order_by('date').search("Event", order_by_relevance=False)

# Events ordered by date
[<EventPage: Easter>, <EventPage: Halloween>, <EventPage: Christmas>]

Аннотирование результатов с оценкой

Для каждого совпавшего результата Elasticsearch вычисляет «оценку», которая представляет собой число, отражающее релевантность результата запросу пользователя. Результаты обычно упорядочиваются на основе оценки.

В некоторых случаях доступ к оценке полезен (например, для программно объединения двух запросов для разных моделей). Вы можете добавить оценку к каждому результату, вызвав метод .annotate_score(field) в SearchQuerySet.

Например:

>>> events = EventPage.objects.search("Event").annotate_score("_score")
>>> for event in events:
...    print(event.title, event._score)
...
("Easter", 2.5),
("Halloween", 1.7),
("Christmas", 1.5),

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

Пример представления поиска страницы

Вот пример представления Django, которое можно использовать для добавления страницы «поиск» на ваш сайт:

# views.py

from django.shortcuts import render

from wagtail.models import Page
from wagtail.search.models import Query


def search(request):
    # Search
    search_query = request.GET.get('query', None)
    if search_query:
        search_results = Page.objects.live().search(search_query)

        # Log the query so Wagtail can suggest promoted results
        Query.get(search_query).add_hit()
    else:
        search_results = Page.objects.none()

    # Render template
    return render(request, 'search_results.html', {
        'search_query': search_query,
        'search_results': search_results,
    })

И вот шаблон для него:

{% extends "base.html" %}
{% load wagtailcore_tags %}

{% block title %}Search{% endblock %}

{% block content %}
    <form action="{% url 'search' %}" method="get">
        <input type="text" name="query" value="{{ search_query }}">
        <input type="submit" value="Search">
    </form>

    {% if search_results %}
        <ul>
            {% for result in search_results %}
                <li>
                    <h4><a href="{% pageurl result %}">{{ result }}</a></h4>
                    {% if result.search_description %}
                        {{ result.search_description|safe }}
                    {% endif %}
                </li>
            {% endfor %}
        </ul>
    {% elif search_query %}
        No results found
    {% else %}
        Please type something into the search box
    {% endif %}
{% endblock %}

Результаты поиска с продвижением

«Результаты поиска с продвижением» позволяют редакторам явно связывать релевантный контент с поисковыми запросами, чтобы страницы результатов могли содержать структурированный контент помимо результатов из поисковой системы.

Эта функциональность обеспечивается модулем search_promotions contrib.

© 2014-present Torchbox Ltd and individual contributors.
All rights are reserved.
Licensed under the BSD License.
https://docs.wagtail.org/en/v3.0.3/topics/search/searching.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API