diff --git a/app.py b/app.py index 6efa9116..bd31a808 100755 --- a/app.py +++ b/app.py @@ -9925,28 +9925,71 @@ def api_get_events(): query = query.filter_by(importance=importance) if creator_id: query = query.filter_by(creator_id=creator_id) - # 新增:行业代码过滤(申银万国行业分类) + # 新增:行业代码过滤(申银万国行业分类)- 支持前缀匹配 + # 申万行业分类层级:一级 Sxx, 二级 Sxxxx, 三级 Sxxxxxx + # 搜索 S22 会匹配所有 S22xxxx 的事件(如 S2203, S220309 等) if industry_code: # related_industries 格式: [{"申银万国行业分类": "S370502"}, ...] # 支持多个行业代码,用逗号分隔 - json_path = '$[*]."申银万国行业分类"' + + # 判断是否需要前缀匹配:一级(3字符)或二级(5字符)行业代码 + def is_prefix_code(code): + """判断是否为需要前缀匹配的行业代码(一级或二级)""" + code = code.strip() + # 申万行业代码格式:S + 数字 + # 一级: S + 2位数字 (如 S22) = 3字符 + # 二级: S + 4位数字 (如 S2203) = 5字符 + # 三级: S + 6位数字 (如 S220309) = 7字符 + return len(code) < 7 and code.startswith('S') # 如果包含逗号,说明是多个行业代码 if ',' in industry_code: codes = [code.strip() for code in industry_code.split(',') if code.strip()] - # 使用 OR 条件匹配任意一个行业代码 conditions = [] for code in codes: - conditions.append( - text("JSON_CONTAINS(JSON_EXTRACT(related_industries, :json_path), :code)") - .bindparams(json_path=json_path, code=json.dumps(code)) - ) + if is_prefix_code(code): + # 前缀匹配:使用 JSON_TABLE + LIKE + # 这个子查询找到所有 related_industries 中申万行业代码以指定前缀开头的事件ID + prefix_sql = text(""" + id IN ( + SELECT DISTINCT e2.id FROM event e2 + CROSS JOIN JSON_TABLE( + e2.related_industries, + '$[*]' COLUMNS (sw_code VARCHAR(20) PATH '$."申银万国行业分类"') + ) AS jt + WHERE jt.sw_code LIKE :prefix + ) + """).bindparams(prefix=f"{code}%") + conditions.append(prefix_sql) + else: + # 精确匹配(三级行业代码) + json_path = '$[*]."申银万国行业分类"' + conditions.append( + text("JSON_CONTAINS(JSON_EXTRACT(related_industries, :json_path), :code)") + .bindparams(json_path=json_path, code=json.dumps(code)) + ) query = query.filter(db.or_(*conditions)) else: # 单个行业代码 - query = query.filter( - text("JSON_CONTAINS(JSON_EXTRACT(related_industries, :json_path), :industry_code)") - ).params(json_path=json_path, industry_code=json.dumps(industry_code)) + if is_prefix_code(industry_code): + # 前缀匹配:使用 JSON_TABLE + LIKE + prefix_sql = text(""" + id IN ( + SELECT DISTINCT e2.id FROM event e2 + CROSS JOIN JSON_TABLE( + e2.related_industries, + '$[*]' COLUMNS (sw_code VARCHAR(20) PATH '$."申银万国行业分类"') + ) AS jt + WHERE jt.sw_code LIKE :prefix + ) + """).bindparams(prefix=f"{industry_code}%") + query = query.filter(prefix_sql) + else: + # 精确匹配(三级行业代码) + json_path = '$[*]."申银万国行业分类"' + query = query.filter( + text("JSON_CONTAINS(JSON_EXTRACT(related_industries, :json_path), :industry_code)") + ).params(json_path=json_path, industry_code=json.dumps(industry_code)) # 新增:关键词/全文搜索过滤(MySQL JSON) if search_query: like_pattern = f"%{search_query}%"