django-elasticsearch-dsl-drf 搜索服务搭建教学
一、整体架构
本搜索服务基于 Django + django-elasticsearch-dsl + django-elasticsearch-dsl-drf 搭建,实现MySQL业务数据与Elasticsearch搜索引擎的联动,提供标准化、可分页、可筛选、可排序的全文搜索API服务。
整体架构流转逻辑:Django模型数据 → ES文档映射 → DRF视图接口 → 前端搜索请求
架构组成说明:
Django Model(SKU):业务数据源,存储商品SKU基础数据
django-elasticsearch-dsl:实现Django与ES的数据映射、索引定义、数据自动同步
django-elasticsearch-dsl-drf:基于DRF封装ES查询能力,提供搜索、过滤、排序、分页接口
Elasticsearch 7.17.x:底层搜索引擎,通过倒排索引实现高效全文检索
documents.py:定义ES索引结构、字段映射、数据过滤规则
DocumentViewSet:核心视图类,搭配各类过滤器实现搜索功能
二、环境依赖安装
搭建前需安装指定版本依赖包,适配ES7.x版本,保证框架兼容性。
pip install django-elasticsearch-dsl==7.3 pip install django-elasticsearch-dsl-drf三、项目配置(settings.py)
在项目配置文件中注册ES相关应用,并配置Elasticsearch服务连接地址。
# settings/dev.py INSTALLED_APPS = [ # 原有项目应用 'django_elasticsearch_dsl', # ES DSL核心集成 'django_elasticsearch_dsl_drf', # ES DSL DRF接口集成 ] # Elasticsearch连接配置 ELASTICSEARCH_DSL = { 'default': { 'hosts': 'http://192.168.36.129:9200', # ES服务地址 }, }四、定义ES文档(documents.py)
该文件用于绑定Django模型、定义ES索引名称、字段结构、索引配置,同时实现数据过滤和自动同步能力。通过装饰器完成自动注册,无需手动编写信号,即可实现MySQL数据增删改自动同步ES。
# apps/goods/documents.py from django_elasticsearch_dsl import Document, fields from django_elasticsearch_dsl.registries import registry from .models import SKU @registry.register_document class SKUDocument(Document): """商品SKU搜索文档""" # 自定义关联字段 id = fields.IntegerField(attr='id') category_name = fields.TextField(attr='category.name') class Index: # ES索引名称 name = 'meiduo_dsl' # 索引分片配置 settings = { 'number_of_shards': 1, 'number_of_replicas': 0, } class Django: # 绑定Django业务模型 model = SKU # 自动映射的模型基础字段 fields = [ 'name', 'caption', 'price', 'sales', 'stock', 'is_launched', ] @classmethod def get_queryset(cls): """只索引上架商品,过滤无效数据""" return SKU.objects.filter(is_launched=True)五、创建ES数据序列化器(serializers.py)
用于序列化ES查询到的文档数据,统一接口返回格式,指定需要对外暴露的字段。
# apps/goods/serializers.py from django_elasticsearch_dsl_drf.serializers import DocumentSerializer from .documents import SKUDocument class SKUDocumentSerializer(DocumentSerializer): """ES文档序列化器""" class Meta: document = SKUDocument # 接口返回字段 fields = [ 'id', 'name', 'caption', 'price', 'sales', 'stock', 'category_name', 'is_launched', ]六、编写搜索视图(views.py)
基于框架提供的DocumentViewSet实现接口能力,配置分页、搜索、过滤、排序后端,实现完整的商品搜索功能。
# apps/goods/views.py from rest_framework.pagination import PageNumberPagination from django_elasticsearch_dsl_drf.viewsets import DocumentViewSet from django_elasticsearch_dsl_drf.filter_backends import ( FilteringFilterBackend, OrderingFilterBackend, SearchFilterBackend, DefaultOrderingFilterBackend, ) from .documents import SKUDocument from .serializers import SKUDocumentSerializer # 自定义分页类 class StandardResultsSetPagination(PageNumberPagination): """标准分页配置""" page_size = 10 page_size_query_param = 'page_size' max_page_size = 100 class SKUDocumentViewSet(DocumentViewSet): """SKU商品搜索接口视图""" document = SKUDocument serializer_class = SKUDocumentSerializer pagination_class = StandardResultsSetPagination # 启用的过滤器后端 filter_backends = [ SearchFilterBackend, # 全文关键词搜索 FilteringFilterBackend, # 精确条件过滤 OrderingFilterBackend, # 自定义排序 DefaultOrderingFilterBackend, # 默认排序兜底 ] # 全文搜索匹配字段 search_fields = ( 'name', 'caption', ) # 精确过滤字段映射 filter_fields = { 'is_launched': 'is_launched', } # 支持排序的字段 ordering_fields = { 'price': 'price', 'sales': 'sales', } # 默认排序规则:销量降序 ordering = ('-sales',)七、配置路由(urls.py)
通过DRF路由注册视图,生成标准化的搜索接口地址。
# apps/goods/urls.py from rest_framework.routers import DefaultRouter from .views import SKUDocumentViewSet router = DefaultRouter() # 注册搜索接口路由 router.register('skus/dsl_search', SKUDocumentViewSet, basename='skus_dsl_search') urlpatterns = router.urls八、索引创建与数据导入命令
项目配置完成后,需执行命令创建ES索引、导入存量业务数据,接口才可正常使用。
# 进入项目根目录 cd d:\Git01\git-code\meiduo-test01\meiduo_mall # 1. 创建ES索引结构 python manage.py search_index --create # 2. 导入模型数据至ES索引 python manage.py search_index --populate # 3. 重建索引(修改文档字段、索引配置后使用) python manage.py search_index --rebuild # 4. 删除索引 python manage.py search_index --delete九、项目文件结构
meiduo_mall/ ├── meiduo_mall/ │ ├── apps/ │ │ └── goods/ │ │ ├── documents.py # ES索引文档定义 │ │ ├── serializers.py # ES数据序列化器 │ │ ├── views.py # 搜索接口视图 │ │ └── urls.py # 接口路由配置 │ └── settings/ │ └── dev.py # 项目配置文件(ES配置) └── requirements.txt # 项目依赖文件十、接口查询参数使用说明
1. 全文搜索
通过search参数匹配商品名称、简介关键词
http://127.0.0.1:8000/skus/dsl_search/?search=华为
http://127.0.0.1:8000/skus/dsl_search/?search=iPhone
2. 精确过滤
通过is_launched参数过滤上架/下架商品
- http://127.0.0.1:8000/skus/dsl_search/?is_launched=true
3. 排序查询
通过ordering参数实现升降序排序
价格升序:/skus/dsl_search/?ordering=price
价格降序:/skus/dsl_search/?ordering=-price
销量降序:/skus/dsl_search/?ordering=-sales
4. 分页查询
通过page、page_size控制分页
- /skus/dsl_search/?page=1&page_size=10
5. 组合查询
支持搜索、排序、分页多参数组合使用
- /skus/dsl_search/?search=华为&ordering=-price&page=1&page_size=5
十一、接口响应格式
接口返回标准化分页JSON数据,包含总数量、上下页地址、结果列表。
{ "count": 8, "next": "http://127.0.0.1:8000/skus/dsl_search/?page=2&search=华", "previous": null, "results": [ { "id": 9, "name": "华为 HUAWEI P10 Plus...", "caption": "wifi双天线设计!...", "price": 3388.0, "sales": 21, "stock": 6, "category_name": "手机", "is_launched": true } ] }十二、核心组件功能说明
| 组件 | 核心作用 |
|---|---|
| Document | 定义ES索引结构、字段映射、索引配置,绑定Django模型 |
| DocumentSerializer | 序列化ES文档数据,统一接口返回字段与格式 |
| DocumentViewSet | 核心视图,整合所有查询能力,提供搜索API接口 |
| SearchFilterBackend | 实现全文关键词搜索功能 |
| FilteringFilterBackend | 实现字段精确过滤功能 |
| OrderingFilterBackend | 实现自定义字段排序功能 |
| DefaultOrderingFilterBackend | 配置接口默认排序规则 |
十三、数据自动同步机制
通过@registry.register_document装饰器自动完成数据同步,无需手动编写信号处理器:
Django中执行 SKU.save()(新增/修改数据)→ ES索引自动更新对应文档
Django中执行 SKU.delete()(删除数据)→ ES索引自动删除对应文档
优势:零代码实现MySQL与Elasticsearch数据实时同步,降低开发成本。
十四、技术对比:Haystack vs dsl-drf
| 对比项 | Haystack | dsl-drf |
|---|---|---|
| 索引定义方式 | search_indexes.py + 模板文件 | 纯 documents.py 配置,更简洁 |
| 数据同步 | 需手动配置信号处理器 | 装饰器自动同步,无需手动配置 |
| 查询方式 | HaystackViewSet | DocumentViewSet,贴合DRF规范 |
| 过滤/排序能力 | 功能有限 | 功能强大、配置灵活 |
| ES版本适配 | 需自定义适配 | 原生适配ES7.x版本 |
| 代码量 | 冗余代码较多 | 精简高效 |
十五、搭建流程总结
安装依赖:安装dsl核心包与drf适配包
项目配置:注册应用,配置ES服务连接地址
定义索引:编写documents.py,绑定模型、定义索引结构与数据规则
编写序列化器:规范ES数据返回格式
编写视图:配置分页、搜索、过滤、排序后端,实现接口能力
配置路由:注册视图路由,生成可访问接口
初始化数据:执行命令创建索引、导入存量数据,完成服务搭建
后续会整理ES数据库相关知识