Flask结合RediSearch实现Redis Payload内容检索返回空列表问题求助
问题排查及解决方案
核心问题原因
RediSearch提供的AutoCompleter自动补全组件仅对存入的Suggestion对象的字符串主键(你代码里传入的n,也就是接口参数name的值)做前缀匹配检索,完全不会对Payload字段内的内容做索引和匹配,你尝试搜索Payload内的值自然拿不到结果,属于组件能力使用错配。
其他潜在问题
- 你提供的新增数据接口
add()没有添加Flask路由装饰器@app.route('/add'),接口无法被调用,数据根本没有存入Redis,搜索自然返回空列表。 get接口没有对prefix参数做非空校验,如果传入空值或者全空格的参数,strip后得到空字符串,也会返回空结果。- 两个接口的异常仅做控制台打印,没有返回错误信息,无法快速判断调用阶段的报错。
修复方案
方案1:仅使用AutoCompleter做前缀匹配(仅能搜索name字段)
先修复基础代码问题,测试基础功能是否正常:
首先修正新增接口的路由配置:
# 接口调用示例:localhost/add?name=<name> @app.route('/add') # 补上缺失的路由装饰器 def add(): try: name = request.args.get('name') if not name or not name.strip(): return "name参数不能为空", 400 n = name.strip() payload = { "data": { "value": "1", } } ac.add_suggestions(Suggestion(n,1.0,json.dumps(payload))) return "Added Successfully" except Exception as e: print(e) return f"Addition Failed: {str(e)}", 500
然后修正查询接口的参数校验:
# 接口调用示例:localhost/get?prefix=<name前缀> @app.route('/get') def get(): try: prefix = request.args.get('prefix') if not prefix or not prefix.strip(): return jsonify([]), 400 n = prefix.strip() result= ac.get_suggestions(n, fuzzy = True,with_payloads=True) return json.dumps([{'id': item.string, 'score': item.score,'payload':json.loads(item.payload)} for item in result]) except Exception as e: print(e) return jsonify([]), 500
测试流程:先调用http://localhost/add?name=test存入数据,再调用http://localhost/get?prefix=te即可拿到对应结果,注意此时只能搜索name字段的前缀,无法搜索payload内的value=1。
方案2:需要搜索Payload内容,换用RediSearch全文索引
如果必须检索Payload内部的字段,放弃AutoCompleter,使用RediSearch的全文索引功能,把需要搜索的字段都加入索引:
示例代码:
from redisearch import Client, TextField, NumericField, Query # 初始化全文索引客户端 client = Client('my_idx') # 首次运行创建索引,包含name字段和payload内的value字段 try: client.create_index([ TextField('name', sortable=True), NumericField('data_value') ]) except: # 索引已存在跳过创建 pass # 新增数据接口 @app.route('/add') def add(): try: name = request.args.get('name') if not name or not name.strip(): return "name参数不能为空", 400 n = name.strip() # 直接存为文档,把需要搜索的字段拆出来 client.add_document( f"doc:{n}", # 文档id name = n, data_value = 1 # payload里的value字段单独存用于检索 ) return "Added Successfully" except Exception as e: print(e) return f"Addition Failed: {str(e)}", 500 # 搜索接口,支持搜索name和data_value @app.route('/search') def search(): try: keyword = request.args.get('keyword', '').strip() if not keyword: return jsonify([]) # 全文搜索,匹配name或者data_value q = Query(keyword) res = client.search(q) result = [{'id': doc.id, 'name': doc.name, 'data_value': doc.data_value} for doc in res.docs] return jsonify(result) except Exception as e: print(e) return jsonify([])
配置完成后即可搜索payload里的内容,比如调用http://localhost/search?keyword=1就能拿到data_value为1的所有数据。
内容的提问来源于stack exchange,提问作者Rahul
相关产品推荐
相关产品推荐

