搜索多个模型(Elasticsearch)

2024-09-30 06:21:15 发布

您现在位置:Python中文网/ 问答频道 /正文

我在我的应用程序中添加了第二个模型,现在我还想在字段中搜索该模型,并在与第一个模型相同的视图中返回它。在

在视图.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被搜索到匹配项,如何在此处添加第二个匹配项文档.py在这个功能中? 或者更具体地说,要搜索多个文档,我必须在这行中更改什么?在

^{pr2}$

这就是“qs”的由来(基本.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>

在文档.py公司名称:

提前谢谢


Tags: 文档py模型divform视图searchget
3条回答

接受的答案是正确的,但效率不高,因为它从数据库中提取行,将结果转换为查询集,最后进行链和排序。。。在

我希望我的回答能帮助别人。我使用的是django oscar和dajngo elasticsearch dsl,我假设您至少使用了elasticsearch dsl。所以你可以简单地

# *********************************************** documents.py in user module
from django_elasticsearch_dsl import Document
from django_elasticsearch_dsl.registries import registry
from oscar.core.compat import get_user_model

User = get_user_model()

@registry.register_document
class UserDocument(Document):

    class Index:
        name = 'users'
        settings = {
            'number_of_shards': 1,
            'number_of_replicas': 0
        }

    class Django:
        model = User # <  User model class 

        fields = [
            'first_name',
            'last_name',
            'username'
        ]


# *********************************************** documents.py in product module
from django_elasticsearch_dsl import Document, TextField
from django_elasticsearch_dsl.registries import registry
from oscar.core.loading import get_model

Product = get_model('catalogue', 'product')

@registry.register_document
class ProductDocument(Document):

    upc = TextField(attr='upc', required=False)

    class Index:
        name = 'products'
        settings = {
            'number_of_shards': 1,
            'number_of_replicas': 0
        }

    class Django:
        model = Product # <  Product model class

        fields = [
            'title',
            'description'
        ]


# *********************************************** search method
from django.shortcuts import render
from elasticsearch_dsl import Search

def global_search(request):

    q = request.GET.get('q')
    objects = ''

    if q:
        search = Search(index=['users', 'products'])
        objects = search.query("multi_match", query=q, fields=['first_name', 'last_name', 'username', 'title', 'description', 'upc'])

    return render(request, 'oscar/search/search.html', {'objects': objects})

让它像这样工作:

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帖子列表

match query中,您已经将查询中的所有标记作为SQL中的OR查询进行搜索。在您的例子中,如果您有一个multimatch query字段,则表示您正在针对这3个字段中的任何一个搜索查询中的任何标记的匹配项-如果您没有将任何特定的映射分配给ES,则意味着您的文本字段已处理了一个standard analyzer请阅读here,该字段将字符串分隔为空格上的标记。因此,要添加一个要查询的新键,只需将一个新值连接到字符串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"

相关问题 更多 >

    热门问题