Django + Docker 搭建 Elasticsearch 全文检索完整教程
在 Django 项目中集成 Elasticsearch 实现全文检索,已成为电商平台和内容管理系统的标配功能。而 Docker 容器化技术的加持,让环境部署变得异常简单高效。接下来,本文将以手把手的方式,带你启动 Elasticsearch 服务,并通过 Haystack 将其与 Django 无缝对接。
使用 Docker 安装 Elasticsearch 并配置 IK 中文分词器
1. 获取 Elasticsearch-ik 镜像
推荐使用官方已整合 IK 分词器的镜像,省去手动安装的繁琐步骤。以下两种方式均可获取:
# 方法一:从 Docker 仓库拉取镜像 $ sudo docker image pull delron/elasticsearch-ik:2.4.6-1.0 # 方法二:加载本地 tar 镜像文件 $ sudo docker load -i elasticsearch-ik-2.4.6_docker.tar
2. 配置 Elasticsearch-ik
将教学资料中的 elasticsearch-2.4.6 目录复制到 home 目录下,然后编辑 /home/python/elasticsearch-2.4.6/config/elasticsearch.yml 的第 54 行,将 IP 地址替换为宿主机的真实 IP(由于 Docker 采用 network=host 模式,必须填写宿主机 IP)。

3. 运行容器
$ sudo docker run -dti --name=elasticsearch --network=host -v /home/python/elasticsearch-2.4.6/config:/usr/share/elasticsearch/config delron/elasticsearch-ik:2.4.6-1.0
容器启动后,请检查日志文件,确保无报错信息,并确认 Elasticsearch 服务已在 9200 端口正常监听。

Haystack 简介与安装配置详解
1. Haystack 是什么
Haystack 是 Django 生态系统中专为对接搜索引擎设计的组件,扮演着“中间人”的角色。在 Django 中编写代码时,你无需关心底层使用的是 Elasticsearch、Whoosh 还是 Solr——Haystack 提供了统一的接口。更换后端仅需修改一行配置,非常方便。
2. 安装依赖
$ pip install django-haystack $ pip install elasticsearch==2.4.1
注意:Elasticsearch 的 Python 客户端版本必须与服务器端版本保持一致,本例中使用的版本是 2.4.1。
3. 注册应用与路由
# 在 settings.py 中注册 Haystack 应用
INSTALLED_APPS = [
'haystack', # 全文检索模块
]
# 主路由配置,添加搜索 URL
path('search/', include('haystack.urls')),
4. 配置搜索引擎后端
在 settings.py 中添加以下配置:
HAYSTACK_CONNECTIONS = {
'default': {
'ENGINE': 'haystack.backends.elasticsearch_backend.ElasticsearchSearchEngine',
'URL': 'https://192.168.103.158:9200/', # 请替换为你的 Elasticsearch 宿主机 IP 地址
'INDEX_NAME': 'meiduo_mall', # 自定义索引库名称,例如 meiduo_mall
},
}
另外,还有一个可选配置,强烈建议添加:
HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.RealtimeSignalProcessor'
该配置的作用是:当 Django 模型数据发生增、删、改操作时,Haystack 会自动通知 Elasticsearch 实时更新索引,避免手动重建。对于需要实时搜索结果的业务场景,这几乎是必选项。
Haystack 创建数据索引详解
1. 创建索引类
索引类用于向 Haystack 和 Elasticsearch 声明哪些字段可供搜索。你需要在应用目录下新建一个名为 search_indexes.py 的文件(文件名必须固定),并在其中编写索引类。
例如,为 SKU 模型实现全文检索,代码如下:
from haystack import indexes
from .models import SKU # 请根据实际模型替换
class SKUIndex(indexes.SearchIndex, indexes.Indexable):
"""SKU 模型索引数据类"""
text = indexes.CharField(document=True, use_template=True)
def get_model(self):
return SKU
def index_queryset(self, using=None):
return self.get_model().objects.filter(is_launched=True)
参数说明:
text字段设置了document=True,表示该字段是主要的关键字搜索字段。use_template=True意味着该字段的索引内容通过一个独立的模板文件定义,从而可以将多个模型字段组合成一个索引值。
2. 创建 text 字段的索引模板文件
在 templates 目录下,按照路径 templates/search/indexes/goods/sku_text.txt 创建文件(注意文件名必须为模型名小写_text.txt),文件内容如下:
{{ object.id }}
{{ object.name }}
{{ object.caption }}
这样,当用户搜索某个关键词时,Elasticsearch 会同时匹配 SKU 的 id、name 和 caption 字段。
3. 手动生成初始索引
确保数据库中已有数据,然后执行以下命令:
python manage.py rebuild_index
该命令会先清空已有索引,再重新构建。如果只需增量更新,应使用 update_index 命令。
4. 在视图中调用搜索
Haystack 内置了默认的搜索视图,但如果需要返回 JSON 格式数据供前端使用,你可以自定义视图,示例如下:
from django.shortcuts import render
import json
from django.conf import settings
from django.core.paginator import InvalidPage, Paginator
from django.http import Http404, HttpResponse, JsonResponse
from haystack.forms import ModelSearchForm
from haystack.query import EmptySearchQuerySet
RESULTS_PER_PAGE = getattr(settings, 'HAYSTACK_SEARCH_RESULTS_PER_PAGE', 20)
def basic_search(request, load_all=True, form_class=ModelSearchForm,
searchqueryset=None, extra_context=None, results_per_page=None):
query = ''
results = EmptySearchQuerySet()
if request.GET.get('q'):
form = form_class(request.GET, searchqueryset=searchqueryset, load_all=load_all)
if form.is_valid():
query = form.cleaned_data['q']
results = form.search()
else:
form = form_class(searchqueryset=searchqueryset, load_all=load_all)
paginator = Paginator(results, results_per_page or RESULTS_PER_PAGE)
try:
page = paginator.page(int(request.GET.get('page', 1)))
except InvalidPage:
result = {"code": 404, "msg": 'No file found!', "data": []}
return HttpResponse(json.dumps(result), content_type="application/json")
context = {
'form': form,
'page': page,
'paginator': paginator,
'query': query,
'suggestion': None,
}
if results.query.backend.include_spelling:
context['suggestion'] = form.get_suggestion()
if extra_context:
context.update(extra_context)
jsondata = []
for result in page.object_list:
data = {
'pk': result.object.pk,
'title': result.object.title,
'desc': result.object.desc,
}
jsondata.append(data)
result = {"code": 200, "msg": 'Search successfully!', "data": jsondata}
return JsonResponse(result, content_type="application/json")
该视图接收 ?q=关键词 参数,返回分页后的 JSON 数据。你可以根据实际模型字段调整 data 字典中的键值。
总结
整个流程归纳起来,只有三个核心步骤:使用 Docker 启动 Elasticsearch → 安装并配置 Haystack → 编写索引类和模板文件。真正掌握 Haystack 的“索引类 + 模板文件”机制后,后续更换搜索引擎或调整字段都会变得非常灵活。希望这份实战指南能助你少走弯路,快速实现全文检索功能。
