Spec-Zone.ru › Wagtail 2

Поиск

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

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

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

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

# Search future EventPages
>>> from wagtail.core.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
])

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

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

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

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

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

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

Вот пример использования ключевого аргумента 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)

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

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

Например:

>>> 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.core.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 %}

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

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

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

  • Предыдущая Индексирование
  • Следующая Бэкенды

Содержание страницы

  • Поиск
    • Поиск набора QuerySet
      • Поиск страниц
      • Поиск с автодополнением
      • Поиск изображений, документов и пользовательских моделей
      • Указание полей для поиска
      • Фильтрованный поиск
      • Изменение поведения поиска
        • Оператор поиска
        • Поиск по фразам
        • Сложные запросы поиска
        • Разбор строки запроса
        • Пользовательское упорядочение
        • Аннотирование результатов оценкой
    • Пример представления страницы поиска
    • Результаты поиска с повышенным приоритетом

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

Spec-Zone.ru

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