Django Elasticsearch DSL实现搜索建议遇空结果问题求助
搞定Django Elasticsearch DSL的搜索建议空结果问题
嘿,我一眼就瞅出你这问题的症结了——你用错了suggester类型!你在Document里定义的是CompletionField,但查询的时候却用了term suggester,这俩根本不搭,难怪返回空结果。下面给你一步步捋清楚怎么修复:
1. 先确认Document的Completion字段没问题
你documents.py里的title.suggest字段定义其实是对的,不过可以加几个参数让建议更顺手,比如允许一定的输入错误、限制输入长度这些,参考下面的写法:
@INDEX.doc_type class MovieDocument(DocType): """Movie Elasticsearch document.""" id = fields.IntegerField(attr='id') title = fields.StringField( analyzer=html_strip, fields={ 'raw': fields.KeywordField(), 'suggest': fields.CompletionField( # 可选参数,按需调整 preserve_separators=True, # 保留分隔符比如空格 preserve_position_increments=True, max_input_length=50 # 限制输入的最大长度 ), } ) summary = fields.StringField( analyzer=html_strip, fields={ 'raw': fields.KeywordField(), } )
2. 必须重建索引!划重点!
修改完Document之后,千万别忘了重新生成Elasticsearch索引并同步数据——不然新的suggest字段根本不会生效。跑这两条命令:
# 先删掉旧索引(如果之前的索引已经存在) python manage.py search_index --delete # 重建索引并把Django里的电影数据同步过去 python manage.py search_index --rebuild
3. 重写Views里的搜索建议查询逻辑
你得用completion类型的suggester,而不是term。而且要注意,查询的字段是title.suggest,不是title——因为你把suggest字段放在了title的子字段里。正确的代码如下:
from elasticsearch_dsl import Search from elasticsearch_dsl.connections import connections # 建议用Django Elasticsearch DSL自带的connections获取客户端,比直接实例化更稳妥 client = connections.get_connection() search_in_title = 'search term goes here' # 创建Search对象,指定要查询的索引 sreq = Search(using=client, index='search_movies') # 添加completion类型的建议查询 ssug = sreq.suggest( 'title_suggestions', # 建议的名称,随便起个好认的 search_in_title, # 用户输入的搜索词 completion={ 'field': 'title.suggest', # 这里必须是你定义的suggest字段路径 # 可选:允许模糊匹配,比如用户输错一两个字也能出建议 'fuzzy': { 'fuzziness': 1 }, # 可选:设置返回多少条建议,默认是5条 'size': 5 } ) # 执行查询 response = ssug.execute() # 提取建议结果 if response.suggest.title_suggestions: suggestions = response.suggest.title_suggestions[0].options # 遍历获取每个建议的文本 for option in suggestions: print(option.text) # 这里可以把结果传给前端模板
最后再敲几个关键点
- 字段路径别写错:一定要写
title.suggest,不是title——你在Document里把suggest作为title的子字段定义的,Elasticsearch里存的路径就是这个。 - suggester类型要匹配:
CompletionField专门对应completionsuggester,termsuggester是给普通文本字段用的,两者不兼容。 - 索引重建不能忘:每次改了Document的字段定义,都要重建索引,不然Elasticsearch里没有对应字段的数据,自然查不出结果。
内容的提问来源于stack exchange,提问作者kampias
相关产品推荐
相关产品推荐

