Django之Haystack对接搜索引擎框架Elasticsearch

news2024/9/25 17:19:01

Django之Haystack对接Elasticsearch

  • Haystack
    • 概述
    • 安装依赖
    • 环境准备
    • Haystack配置
  • Haystack建立数据索引
    • 创建模型对象
    • 创建搜索索引类
    • 创建模板文件
    • 执行数据库迁移
    • 生成索引
    • 渲染模板
    • 执行测试
  • 搜索请求和结果渲染的自定义处理
    • 概述
    • 创建搜索视图
    • 配置URL
    • 创建搜索模板
    • 自定义结果渲染
    • 执行测试
  • 其他
    • 添加分页功能
    • 自定义搜索查询
    • 使用Facets
    • 高级排序
    • 使用拼音搜索或模糊搜索

Haystack

概述

Haystack是在Django中对接搜索引擎的框架,搭建用户和搜索引擎之间的沟通桥梁。它提供了一种简化的方式来集成不同的搜索引擎,如Elasticsearch、Whoosh、Solr等。

Elasticsearch的底层是开源库Lucene。Python是没法直接使用Lucene,必须写代码去调用它的接口。因此,在Django中可以通过使用Haystack对接 Elasticsearch服务端

Haystack的主要功能包括:

统一接口:Haystack为多个搜索引擎提供了统一的API,使得在不同的搜索引擎之间切换变得简单。

搜索索引:它允许开发者为Django模型创建搜索索引,从而能够对模型中的数据进行高效的搜索。

查询构建:Haystack提供了简洁的查询构建工具,支持复杂的搜索条件和过滤。

模板支持:可以通过模板轻松自定义搜索结果的展示。

灵活性:Haystack支持多种后端搜索引擎,开发者可以根据项目需求选择最合适的搜索解决方案。

文档:https://docs.haystacksearch.org/en/master/tutorial.html

安装依赖

首先,需要安装django-haystackelasticsearch

在Django项目中安装Haystack库

pip install django-haystack

注意:使用elasticsearch时,使用如下命令安装

# pip install elasticsearch==7.5.1

pip install "django-haystack[elasticsearch]"

环境准备

创建应用模块product

python manage.py startapp product

在Django项目的settings.py文件中,注册应用product,同时将haystack添加到INSTALLED_APPS

INSTALLED_APPS = [
    'apps.product',
    'haystack',
]

在项目路径下注册路由

urlpatterns = [
    # path('admin/', admin.site.urls),
    path('search/', include('haystack.urls')),
    path('product/', include('product.urls')),
]

Haystack配置

在Django的settings.py文件中配置Haystack和Elasticsearch

HAYSTACK_CONNECTIONS = {
    'default': {
   		# 这里使用Elasticsearch7.x版本,如果使用其他版本,请相应地修改ENGINE的值
        'ENGINE': 'haystack.backends.elasticsearch7_backend.Elasticsearch7SearchEngine',
        # Elasticsearch服务器ip地址,端口号固定为9200
        'URL': 'http://127.0.0.1:9200/',
        # Elasticsearch建立的索引库的名称
        'INDEX_NAME': 'demo',
    },
}

# 当数据库改变时,会自动更新索引
# Haystack可以让Elasticsearch实时生成新数据的索引,即当添加、修改、删除数据时,自动生成索引
HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.RealtimeSignalProcessor'

# 控制每页显示数量
HAYSTACK_SEARCH_RESULTS_PER_PAGE = 20

Haystack建立数据索引

创建模型对象

在product子应用的models.py文件创建模型对象

from django.db import models

class Product(models.Model):
    name = models.CharField(max_length=20, verbose_name='名称')
    price = models.DecimalField(max_digits=10, decimal_places=2, verbose_name='单价')
    stock = models.IntegerField(default=0, verbose_name='库存')
    is_existed = models.BooleanField(default=True, verbose_name='是否上架')

    class Meta:
        db_table = 'tb_product'
        verbose_name = '产品'
        verbose_name_plural = verbose_name

    def __str__(self):
        return '%s: %s' % (self.id, self.name)

创建搜索索引类

创建一个搜索索引类来定义要搜索的模型,指明让搜索引擎对哪些字段建立索引,即通过哪些字段的关键字来检索数据,通常在应用目录下创建一个search_indexes.py文件

在product子应用的目录下创建search_indexes.py文件,在这个文件下写索引类

from haystack import indexes

from .models import Product


# ProductIndex索引数据模型类
class ProductIndex(indexes.SearchIndex, indexes.Indexable):
 
	# text表示被查询的字段,用户搜索的是这些字段的值,具体被索引的字段写在另一个文件里。
    text = indexes.CharField(document=True, use_template=True)

    stock = indexes.IntegerField(model_attr='stock')

    price = indexes.FloatField(model_attr='price')

    def get_model(self):
        # 返回建立索引的模型类
        return Product

    def index_queryset(self, using=None):
        # 返回要建立索引的数据查询集
        return self.get_model().objects.all()

注意:

  • 类名必须是需要检索的ModelName+Index,如:Product模型类+Index,即ProductIndex

  • 每个索引类必须有且只能有一个字段为document=True,代表haystack和搜索引擎将使用此字段的内容作为索引进行检索。其他的字段只是附属的属性,方便调用,并不作为检索数据。

  • 如果使用一个字段设置了document=True,则一般约定此字段名为text,表名该字段是主要进行关键字查询的字段,用于构造索引,只不过具体构造索引的值写在另一个文件内。

  • haystack提供了use_template=True在text字段,允许使用数据模板去建立搜索引擎索引的文件

  • stock 、price 用于以索引查询到的返回内容

  • get_model方法用于指明建立索引的对应模型

  • index_queryset方法用于返回建立索引的数据查询集

创建模板文件

templates目录下创建search/indexes/yourapp/yourmodel_text.txt字段索引值模板文件,在该文件中定义要索引的字段

例如:

{{ object.field_name }}
yourapp:实际应用名称

yourmodel:实际模型名称

field_name:要索引的实际字段

注意:

这个路径是固定的,如果不按照这个路径配置,就需要在text字段内使用template_name 参数,指定模板文件

例如:这里在templates目录下创建search/indexes/product/product_text.txt文件,具体索引字段如下:

{{ object.name }}
{{ object.price }}

模板文件意思:

当将关键词通过text参数名传递时,此模板指明Product的name、price作为text字段的索引值来进行关键字索引查询,即作为索引的方向

执行数据库迁移

配置连接数据库信息

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'HOST': '127.0.0.1',  # 数据库主机
        'PORT': 3306,  # 数据库端口
        'USER': 'root',  # 数据库用户名
        'PASSWORD': '123456',  # 数据库用户密码
        'NAME': 'demo'  # 数据库名字
    }
}

生成迁移文件,让 Django 知道模型有一些变更

python manage.py makemigrations

创建表结构,同步到数据库中

python manage.py migrate

插入Product模型类对应的tb_product表数据

INSERT INTO `demo`.`tb_product` (`id`, `name`, `price`, `stock`, `is_existed`) VALUES (1, '1号手机', 999.00, 23, 1);
INSERT INTO `demo`.`tb_product` (`id`, `name`, `price`, `stock`, `is_existed`) VALUES (2, '2号手机', 1999.00, 98, 1);
INSERT INTO `demo`.`tb_product` (`id`, `name`, `price`, `stock`, `is_existed`) VALUES (3, '3号手机', 3999.00, 56, 1);
INSERT INTO `demo`.`tb_product` (`id`, `name`, `price`, `stock`, `is_existed`) VALUES (4, '4号手机', 4999.00, 234, 1);
INSERT INTO `demo`.`tb_product` (`id`, `name`, `price`, `stock`, `is_existed`) VALUES (5, '5号手机', 5999.00, 21, 1);

生成索引

运行以下命令来创建并初始化Elasticsearch索引

python manage.py rebuild_index
(django) D:\WorkSpace\Python\django_project>python manage.py rebuild_index
WARNING: This will irreparably remove EVERYTHING from your search index in connection 'default'.
Your choices after this are to restore from backups or rebuild via the `rebuild_index` command.
Are you sure you wish to continue? [y/N] y
Removing all documents from your index because you said so.
All documents removed.
Indexing 5 产品

查看ES,发现索引已创建,并且tb_product表中数据根据索引类配置已生产相应索引数据
在这里插入图片描述

注意:本人在生成初始索引时,遇到如下异常:

haystack.exceptions.MissingDependency: The 'elasticsearch' backend requires the installation of 'elasticsearch'. Please refer to the documentation

最初直接指定版本安装es:

pip install elasticsearch==7.5.1

经过一番折腾,阅读官方文档,推测很有可能是Haystack与Elasticsearch版本不兼容导致的。参考官方文档,使用如下命令安装Elasticsearch,问题得以解决。

pip install "django-haystack[elasticsearch]"

渲染模板

templates目录下创建search/search.html渲染模板文件,用于接收和渲染全文检索的结果。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form method="get" action="/search/">
    <input type="text" name="q" placeholder="产品名称">
    <input type="submit" name="" value="搜索">
</form>

<hr>

<div>
    搜索关键字: <span>{{ query }}</span>
    <hr>
    总页数: <span>{{ page.paginator.num_pages }}</span>
    <hr>
    {% for result in page.object_list %}
        <li>
            <span>{{ result.object.name }}</span>
            <span>{{ result.object.price }}</span>
        </li>
    {% empty %}
        <span>查询无结果</span>
    {% endfor %}
</div>

<!-- 分页导航 -->
<div>
    {% if page.has_previous %}
        <a href="?q={{ query }}&page={{ page.previous_page_number }}">上一页</a>
    {% endif %}

    {% for num in page.paginator.page_range %}
        {% if page.number == num %}
            <span>{{ num }}</span>
        {% else %}
            <a href="?q={{ query }}&page={{ num }}">{{ num }}</a>
        {% endif %}
    {% endfor %}

    {% if page.has_next %}
        <a href="?q={{ query }}&page={{ page.next_page_number }}">下一页</a>
    {% endif %}
</div>

</body>
</html>

执行测试

访问:http://127.0.0.1:8000/search/搜索
在这里插入图片描述

直接访问:http://127.0.0.1:8000/search/?q=手机
在这里插入图片描述

分页搜索:http://127.0.0.1:8000/search/?q=手机&page=2
在这里插入图片描述

搜索请求和结果渲染的自定义处理

概述

自动处理

当在Django中使用 Haystack 和 Elasticsearch 进行搜索时,可以通过注册 haystack.urls 来处理搜索相关的 URL 路由。这样做的好处是,Haystack 提供了默认的视图和 URL 配置,可以方便地处理搜索请求并渲染搜索结果。

手动处理

如果想手动处理搜索请求和渲染结果,而不使用 Haystack 提供的默认视图和 URL 配置,可以编写自己的视图函数来执行搜索操作并将搜索结果传递给模板进行渲染。

创建搜索视图

首先,在应用的views.py中创建一个搜索视图。这个视图将处理GET请求中的搜索关键词,并使用Haystack进行搜索。

from haystack.query import SearchQuerySet

def searchView(request):
    query = request.GET.get('q') # 获取搜索关键词
    if query:
        search_results = SearchQuerySet().filter(text=query) # 根据关键词过滤结果
    else:
        print("kong")
        search_results = [] # 如果没有关键词,返回空结果

    return render(request, 'product/product_search.html', {'search_results': search_results})

配置URL

在应用的urls.py中配置搜索视图的URL。

urlpatterns = [
    path('search/', views.searchView),
]

创建搜索模板

在模板目录中创建一个名为search.html的模板文件。这个模板将用于展示搜索表单和结果。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form method="get" action="/product/search/">
    <input type="text" name="q" placeholder="产品名称">
    <input type="submit" name="" value="搜索">
</form>
<hr>
<div>
    {% for result in search_results  %}
        <li>
            <span>{{ result.object.name }}</span>
            <span>{{ result.object.price }}</span>
        </li>
    {% empty %}
        <span>查询无结果</span>
    {% endfor %}
</div>

</body>
</html>

自定义结果渲染

在模板中,可以访问搜索结果的不同字段。例如,如果模型有多个字段,可以在循环中展示这些字段。

<div>
    {% for result in search_results  %}
        <li>
            <span>{{ result.object.name }}</span>
            <span>{{ result.object.price }}</span>
        </li>
    {% empty %}
        <span>查询无结果</span>
    {% endfor %}
</div>

执行测试

访问:http://127.0.0.1:8000/product/search搜索
在这里插入图片描述

其他

Haystack在Django中提供了一些高级用法,可以帮助实现更复杂和灵活的搜索功能。

添加分页功能

如果搜索结果较多,可以考虑实现分页功能。可以使用Django的内置分页工具:

from django.core.paginator import Paginator

def search_view(request):
    query = request.GET.get('q')
    results = SearchQuerySet().all()

    if query:
        results = results.filter(content=query)

    paginator = Paginator(results, 10)  # 每页10个结果
    page_number = request.GET.get('page')
    page_obj = paginator.get_page(page_number)

    return render(request, 'product/product_search.html', {'page_obj': page_obj, 'query': query})

在模板中,添加分页链接:

<div>
    <span>{{ page_obj.paginator.count }} 条结果</span>
</div>
<ul>
    {% for result in page_obj %}
        <li>
            <a href="{{ result.object.get_absolute_url }}">{{ result.object.title }}</a>
            <p>{{ result.object.description }}</p>
        </li>
    {% empty %}
        <li>没有找到结果。</li>
    {% endfor %}
</ul>

<div>
    <span>页码: </span>
    <span class="pagination">
        {% if page_obj.has_previous %}
            <a href="?q={{ query }}&page=1">第一页</a>
            <a href="?q={{ query }}&page={{ page_obj.previous_page_number }}">上一页</a>
        {% endif %}
        <span>{{ page_obj.number }}</span>
        {% if page_obj.has_next %}
            <a href="?q={{ query }}&page={{ page_obj.next_page_number }}">下一页</a>
            <a href="?q={{ query }}&page={{ page_obj.paginator.num_pages }}">最后一页</a>
        {% endif %}
    </span>
</div>

自定义搜索查询

可以使用Haystack的SearchQuerySet来构建复杂的查询。

使用filter()、exclude()和order_by()等方法来定制搜索结果

from haystack.query import SearchQuerySet

results = SearchQuerySet().filter(content='搜索关键词').exclude(author='某个作者').order_by('-date')

使用Facets

分面搜索允许对搜索结果进行分类和过滤。

from haystack.query import SearchQuerySet

def search_view(request):
    query = request.GET.get('q')
    sqs = SearchQuerySet().filter(content=query)
    
    facets = sqs.facet('category')  # 假设有一个category字段
    return render(request, 'product/product_search.html', {'results': sqs, 'facets': facets})

高级排序

可以根据多个字段进行排序,或者使用自定义的排序逻辑

results = SearchQuerySet().filter(content='关键词').order_by('field1', '-field2')

使用拼音搜索或模糊搜索

在某些情况下,可能需要支持拼音搜索或模糊搜索,可以通过自定义查询来实现

results = SearchQuerySet().filter(content__contains='拼音关键词')

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2164265.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

电脑数据怎么恢复?这10种数据恢复方法你一定要知道!

在如今这个数字化时代&#xff0c;电脑已经成为我们生活和工作中不可或缺的一部分。我们在电脑中存储着大量重要的数据&#xff0c;如照片、文档、视频、音乐等。然而&#xff0c;有时候意外总是不可避免&#xff0c;电脑数据可能会因为各种原因丢失&#xff0c;比如误删除、格…

父母血型与子女血型对照表

人类的血型是有遗传性的&#xff0c;父母的血型直接影响孩子的血型&#xff0c;我们可以根据父母血型推测孩子血型&#xff0c;排除不可能血型&#xff0c;那么下面就由血型分析为大家揭晓下父母血型与孩子血型对照表&#xff08;排除基因突变&#xff09; 血型遗传规律表又称血…

IMS注册流程中的基本路由寻址过程

目录 1. SIP 协议栈在 TCP/IP 中的位置 2. 看看 SIP 协议栈各层的寻址功能 本课程,以 IMS 注册流程为例,讲解 IP 网络网元是如何完成 IP 层寻址的 第一跳:UE->P-CSCF 第二跳:P-CSCF->DNS 第三跳:P-CSCF->I-CSCF 第四跳:I-CSCF->HSS 第五跳:I-CSCF-&…

深入解析Debian与Ubuntu:技术特点与用户使用指南

深入解析Debian与Ubuntu&#xff1a;技术特点与用户使用指南 引言 Debian和Ubuntu作为两大知名的Linux发行版&#xff0c;不仅在历史和理念上有所不同&#xff0c;在技术特点和用户使用方法上也各具特色。本文将深入解析它们的技术特点&#xff0c;并提供用户使用指南&#x…

SSM+Vue大学生社团管理系统

目录 1 项目介绍2 项目截图3 核心代码3.1 Controller3.2 Service3.3 Dao3.4 spring-mybatis.xml3.5 spring-mvc.xml3.5 Vue 4 数据库表设计5 文档参考6 计算机毕设选题推荐7 源码获取 1 项目介绍 博主个人介绍&#xff1a;CSDN认证博客专家&#xff0c;CSDN平台Java领域优质创作…

东华大学《2020年+2022年824自动控制原理真题》 (完整版)

本文内容&#xff0c;全部选自自动化考研联盟的&#xff1a;《25届东华大学824自控考研资料》的真题篇。后续会持续更新更多学校&#xff0c;更多年份的真题&#xff0c;记得关注哦~ 目录 2020年真题 2022年真题 Part1&#xff1a;2020年2022年完整版真题 2020年真题 2022年…

惊艳桌面时钟软件 为你的桌面打造专属时间管理!

在快节奏的现代生活中&#xff0c;时间是最宝贵的资源之一。无论是在工作还是生活中&#xff0c;我们都需要时刻关注时间&#xff0c;在桌面显示一个时钟&#xff0c;可以让你更方便的掌握时间。芝麻时钟 &#xff08;下载地址&#xff1a;https://clock.zhimasoft.cn/?bili&a…

Jmeter——参数化的9种方法

jmeter工具无论做接口测试还是性能测试&#xff0c;参数化都是一个必须掌握且非常有用的知识点。参数化的使用场景: 1&#xff09;多个请求都是同一个ip地址&#xff0c;若服务器地址更换了&#xff0c;则脚本需要更改每个请求的ip 2&#xff09;注册账号&#xff0c;不允许账…

【图形学】数学基础

行矩阵和列矩阵 在图形处理中&#xff0c;矩阵操作时最基本的操作&#xff0c;但是不同的系统中对矩阵的存储是不同&#xff0c;比如OpenGL和Cg中就是不一样的&#xff1a; 比如一个4x4矩阵 [m11,m12,m13,m14m21,m22,m23,m24m31,m32,m33,m34m41,m42,m43,m44]在实现中通常将其…

海康威视网络摄像头校时、修改分辨率等操作汇总!

目录 操作环境&#xff1a; 操作原因&#xff1a; 解决办法&#xff1a; 手动校准时间&#xff0c;随着时间推移&#xff0c;可能再次出现偏差&#xff0c;操作简单&#xff1a; 【IVMS-4200】对设备批量校时操作指导&#xff1a;操作之前先把本地服务器的时间改对&#x…

【学习笔记】Kylin-Desktop-V10-SP1 麒麟系统知识2——账户设置

提示&#xff1a;学习麒麟Kylin-Desktop-V10-SP1系统账户设置相关知识&#xff0c;包含用户名修改、用户密码修改、账户类型修改、开机自动登录、免密登录、添加用户、删除用户&#xff0c;以及修改登录选项相关知识 一、前期准备 成功安装麒麟系统&#xff08;本次实验的安装…

视频压缩成文件怎么弄?4招教会你

视频文件过大&#xff0c;不仅占用存储空间&#xff0c;还影响传输效率。但是&#xff0c;压缩视频时又担心会损失画质。有没有一种方法&#xff0c;能在不牺牲画质的前提下&#xff0c;实现视频文件的压缩呢&#xff1f;答案是肯定的。 想快速学会怎么视频压缩不改变清晰度&a…

手机二要素接口如何用C#实现调用

一、什么是手机二要素&#xff1f; 手机二要素又称运营商二要素&#xff0c;运营商二要素核验&#xff0c;实名核验&#xff0c;手机号核验&#xff0c;手机二要素核验&#xff0c;即传入姓名、手机号码&#xff0c;校验此两项是否一致。实时核验&#xff0c;返回校验结果&…

不在同一局域网怎么远程桌面?非局域网环境下,实现远程桌面访问的5个方法分享!

非局域网环境下&#xff0c;怎么远程桌面&#xff1f;还能做到吗&#xff1f; 在企业管理中&#xff0c;远程桌面访问已成为提高工作效率、实现跨地域协同工作的关键工具。 然而&#xff0c;当被控端与控制端不在同一局域网时&#xff0c;如何实现远程桌面连接成为了许多企业…

ROS学习笔记(二):鱼香ROS — 超便捷的一键安装/配置/换源指令(Ubuntu/ROS/ROS2/IDE等)

文章目录 前言鱼香ROS1 一键安装&#xff1a;快速搭建开发环境2 具体使用2.1 如何开始&#xff1f;2.2 我的常用配置方案2.3 安装示例 3 总结相关链接 前言 关于Ubuntu与ROS的常规安装&#xff0c;可以看这几篇。 SLAM实操入门&#xff08;一&#xff09;&#xff1a;在已有…

特种作业管理系统 —— 企业安全与效率的卓越保障

在当今复杂多变的工业生产和作业环境中&#xff0c;安全与效率是企业发展的两大核心关键。我们深知您在特种作业管理方面面临着诸多挑战&#xff0c;如作业流程的规范性、证件的有效管理以及设备的安全运行等。今天&#xff0c;我们为您带来一款专门解决这些问题的创新产品——…

如何解决项目申报过程中文件管理混乱问题?

在项目申报的复杂流程中&#xff0c;文件管理是一项至关重要的环节。它直接关系到项目信息的完整性、安全性和可访问性。然而&#xff0c;传统的文件管理方式往往面临诸多痛点&#xff0c;如资料分散、权限混乱、版本冲突等。 文件管理痛点 资料分散难管理&#xff1a;在项目…

2024年【黑龙江省安全员C证】报名考试及黑龙江省安全员C证免费试题

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 黑龙江省安全员C证报名考试考前必练&#xff01;安全生产模拟考试一点通每个月更新黑龙江省安全员C证免费试题题目及答案&#xff01;多做几遍&#xff0c;其实通过黑龙江省安全员C证模拟考试很简单。 1、【多选题】《…

如何搭建测试平台?理清思路很重要

01 测试平台 01 职责 一个健康的测试平台体系&#xff0c;对测试人员的职责分工、协作模式会有不同的要求。 测试平台核心的职责是完成高质量的交付已满足业务需求。测试活动包括单元测试、集成测试、接口测试、性能测试等&#xff0c;都是通过这些测试手段&#xff0c;协同…

22k star,最强开源堡垒机,强推

最开始接触jumpserver已经是五年前了&#xff0c;最近又发布了最新的v3版本&#xff0c;迫不及待的就去体验了一波&#xff0c;真心不错&#xff0c;增加很多新的功能&#xff0c;操作真的丝滑&#xff0c;比起公司采购的上个世纪的堡垒机真心好用多了。 1 jumpserver简介 ju…