Поиск нескольких моделей (Elasticsearch) - PullRequest
0 голосов
/ 24 января 2019

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

views.py

#Elasticsearch
def globalsearch_elastic(request):
    qs = request.GET.get('qs')
    page = request.GET.get('page')
    if qs:
        qs = PostDocument.search().query("multi_match", query=qs, fields=["title", "content", "tag"])
        qs = qs.to_queryset()
    else:
        qs = ''
    paginator = Paginator(qs, 10)  # Show 10 results per page
    try:
        qs = paginator.page(page)
    except PageNotAnInteger:
        qs = paginator.page(1)
    except EmptyPage:
        qs = paginator.page(paginator.num_pages)
    return render(request, 'MyProject/search/search_results_elastic.html', {'object_list':qs})

в настоящее время только PostDocument получают поиск совпадений, как мне добавить сюда второй из documents.py в этой функции?или, если быть более точным, что мне нужно изменить в этой строке для поиска нескольких документов?

qs = PostDocument.search().query("multi_match", query=qs, fields=["title", "content", "tag"])

это откуда взято "qs" (base.html):

<div class="globalsearch">
        <form id="searchform" action="{% url 'search' %}" method="get" accept-charset="utf-8">
            <div class="form-row align-items-center">
                <input class="class-search-input-fields" id="searchbox" name="qs" required="required" type="text" placeholder="Search ..."><a>in</a>
                <div class="custom-dropdown">
                    <a>{{ categorysearch_form.category }}</a>
                </div>
                <button class="btn btn-dark" type="submit">
                    <i class="fa fa-search"></i>
                </button>
            </div>
        </form>
    </div>

documents.py:

Заранее спасибо

Ответы [ 2 ]

0 голосов
/ 27 января 2019

Получилось так:

def globalsearch_elastic(request):
    qs = request.GET.get('qs')
    page = request.GET.get('page')
    if qs:
        post = PostDocument.search().query("multi_match", query=qs, fields=["title", "content", "tag"]).to_queryset()
        post_extra = PostExtraDocument.search().query("multi_match", query=qs, fields=["title", "content_preview", "tag"]).to_queryset()
        qs = list(
            sorted(
                chain(post, post_extra),
                key=lambda objects: objects.pk
            ))
    else:
        qs = ''
    paginator = Paginator(qs, 10)  # Show 10 results per page
    try:
        qs = paginator.page(page)
    except PageNotAnInteger:
        qs = paginator.page(1)
    except EmptyPage:
        qs = paginator.page(paginator.num_pages)
    return render(request, 'MyProject/search/search_results_elastic.html', {'object_list': qs})

я знаю, что это, возможно, не "лучший метод", потому что мне всегда нужно загружать все сообщения, сортировать их потом и отображать по дате создания (pk).

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

0 голосов
/ 27 января 2019

В match query вы уже ищете все токены в запросе как запрос ИЛИ в SQL.В вашем случае, если у вас есть поле multimatch query против 3, это означает, что вы ищете совпадение любого вашего токена в вашем запросе с любым из этих 3 полей - если вы не назначили какое-либо конкретное сопоставление для ES, оноозначает, что ваши текстовые поля обработаны с standard analyzer, пожалуйста прочитайте здесь , который разбивает вашу строку в токенах на пробел.Таким образом, чтобы добавить новый ключ для запроса, просто объедините новое значение в строку qs:

from document import DocClass

def globalsearch_elastic(request):
    qs = request.GET.get('qs')
    document = DocClass()
    document_value = document.my_function() # you invoke a function in a class inside document.py that returns to you a string
    page = request.GET.get('page')
    if any([qs, document_value]):
        queryable = " ".join([qs, document_value])
        qs = PostDocument.search().query("multi_match", query=queryable, fields=["title", "content", "tag"])
        qs = qs.to_queryset()
    else:
        return "No values to query"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...