django + elasticsearch + haystack构建全文搜索功能
材料准备
-
es 主角包
-
analysis-ik 插件,用于中文分词,下载后添加文件后缀
.zip -
kibana (可选) 用于可视化查看es数据
注意:版本一定要相同
es
-
安装
将下载的包解压放到合适的位置(一般是/usr/local)
tar -zxvf elasticsearch-7.13.4-linux-x86_64.tar.gz -C /usr/local/elasticsearch/usr/local/elasticsearch没有则创建
修改为如下配置:
/usr/local/elasticsearch/elasticsearch7.13.4/config/elasticsearch.yml... -----------------------------Network----------------------------- # 添加 discovery.type: single-node # 解决跨域问题 # - 修改 network.host: 0.0.0.0 # - 添加 http.cors.enabled: true http.cors.allow-origin: "*" # 开启安全验证(生产环境一般要设置) # xpack.security.enabled: true ...network.host原来就有,剩余三个新增就行
elasticsearch7.13.4/bin/elasticsearch为执行文件,在shell中执行即可启动(注意相对路径和绝对路径)- 生成用户密码
elasticsearch7.13.4/bin/elasticsearch-setup-passwords auto自动生成elasticsearch7.13.4/bin/elasticsearch-setup-passwords interactive交互生成
如果选择第一种自动生成,务必保存输出的密码内容,后续无法查看!- 修改elasticsearch密码(需旧密码)
服务器发送http请求
curl -u elastic -X POST 'localhost:9200/_security/user/elastic/_password' -H 'Content-Type: application/json' -d '{"password": "新密码"}' # 随后根据提示输入旧密码即可。
-
创建用户
es不能直接使用root启动,因此创建一个elastic用户
useradd elastic
更改文件归属chown -R elastic:elastic /usr/local/elasticsearch/elasticsearch-7.13.4 -
启动
/usr/bin/su - elastic -c '/usr/local/elasticsearch/elasticsearch7.13.4/bin/elasticsearch'
/usr/bin/su - elastic 干净切换用户,-去除上个用户的环境
-c切换用户后执行的命令
安装ik插件
将下载的文件解压到es文件夹/elasticsearch7.13.4/plugins中,为了方便,可将解压的ik文件夹命名为ik-7.13.4
重启es即可生效
- 查看插件命令
/usr/local/elasticsearch/elasticsearch7.13.4/bin/elasticsearch-plugin list
配置django
1. 安装模块
pip install elasticsearch==7.13.4
pip install drf-haystack
2. settings.py
INSTALLED_APPS = [
"django.contrib.auth",
"django.contrib.contenttypes",
'haystack',
]
TEMPLATES = [
"DIRS": [BASE_DIR / 'templates'] # es全文索引有用
]
HAYSTACK_CONNECTIONS = {
'default': {
# haystack操作es的核心模块(仅限7版本)
'ENGINE': 'haystack.backends.elasticsearch7_backend.Elasticsearch7SearchEngine',
# es服务端地址
'URL': 'http://127.0.0.1:9200/',
# es索引仓库
'INDEX_NAME': 'haystack', # 在ES生成的索引名称
# 'KWARGS': {
# 'http_auth': ('username', 'password'), # 认证用户名和密码(如果设置了安全验证)
#},
}
}
# 当ORM操作数据库改变时,自动更新es的索引,否则es的索引会找不到新增的数据
HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.RealtimeSignalProcessor'
# 用于同步删除es记录(信号删除未生效,原因暂时未知)
get_identifier = lambda obj: obj.id # obj.id是你的记录主键
HAYSTACK_IDENTIFIER_METHOD = '项目名称.settings.get_identifier'
3. search_indexes.py (固定名称,务必放你的app根目录下)
class CommonUserIndex(indexes.SearchIndex, indexes.Indexable):
# document=True 表示当前字段为全文索引
# use_template=True 表示接下来haystack需要加载一个固定路径的html模板文件,让text与其他索引字段绑定映射关系
text = indexes.CharField(document=True, use_template = True) # 全文索引(可以根据配置,可以包括多个字段索引),省略了model_attr,参与templates名称构成,text名称可改
# 普通索引(单字段,只能提供单个字段值的搜索,所以此处的声明更主要是为了提供给上面的text全文索引使用的)
# es索引名 = indexes.索引数据类型(model_attr="ORM中的字段名") 注意如果字段返回的是json,要json。dumps转换成字符串
username = indexes.IntegerField(model_attr="userinfo__username")
nickname = indexes.CharField(model_attr="nickname")
# 指定与当前es索引模型对接的mysql的ORM模型
def get_model(self):
return models.CommonUser
# # 当用户搜索es索引的文档信息时,对应的提供给客户端的mysql数据行
# def index_queryset(self, using=None):
# return self.get_model().objects.filter(is_delete=False, is_show=True )
4. 创建全文索引配置
api/templates/search/indexes/api/course_text.txt 目录构成必须是templates目录下的search/indexes/子应用目录名
course_text.txt名称构成:模型类名_全文索引变量.txt
{{ object.userinfo.username }}
{{ object.nickname }}
object表示当前orm的模型对应
5. 序列化器
旧序列化器可保留
class CommonUserHaystackSerializer(HaystackSerializer):
class Meta:
index_classes = [CommonUserIndex]
fields = [
'text',
'username',
'nickname'
]
# def to_representation(self, instance):
# """在返回数据前可进行操作"""
# # self.context['request'].request.META['HTTP_HOST'] # 获取请求的来源ip
# instance.id += 1
# return super().to_representation(instance)
6. 视图类
旧视图类可保留
class CommonUserEsView(HaystackViewSet):
"""全文搜索类"""
index_models = [models.CommonUser]
serializer_class = CommonUserHaystackSerializer
# 如果不想用高亮关键字,将HaystackHighlightFilter换成HaystackFilter
filter_backends = [DjangoFilterBackend, HaystackHighlightFilter]
ordering_fields = ('username', 'nickname')
pagination_class = MyPageNumberPagination
7. 路由
router.register('search', account.CommonUserEsView, basename='user-search') # 没有queryset,要指定basename
8. 将mysql数据库数据同步到es
终端执行python manage.py rebuild_index
9. 使用
http://127.0.0.1:8000/api/search/?text=1
即:上面注册的路由加参数 + ?text=xxx
其他:
-
相关命令
python manage.py rebuild_index重建索引 (--noinput忽略确认)python manage.py update_index --age=<num_hours>更新索引,<num_hours>多久前的索引python manage.py clear_index清除索引... --noinput不提示,直接操作
Tips:
- 如果提示Decimal不能json,就float(...)转成浮点数
- 数据类型还有问题,试试json.dumps()

浙公网安备 33010602011771号