#!/usr/bin/env python3 """ 测试 Facets 修复:验证 Pydantic 模型是否正确构建和序列化 """ import sys import os sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) from api.models import SearchResponse, FacetResult, FacetValue def test_facet_models(): """测试 FacetValue 和 FacetResult 模型""" print("=== 测试 1: 创建 FacetValue 对象 ===") facet_value = FacetValue( value="玩具", label="玩具", count=100, selected=False ) print(f"✓ FacetValue 创建成功") print(f" - value: {facet_value.value}") print(f" - count: {facet_value.count}") print(f" - selected: {facet_value.selected}") print("\n=== 测试 2: 创建 FacetResult 对象 ===") facet_result = FacetResult( field="categoryName_keyword", label="商品类目", type="terms", values=[ FacetValue(value="玩具", label="玩具", count=100, selected=False), FacetValue(value="益智玩具", label="益智玩具", count=50, selected=True), ] ) print(f"✓ FacetResult 创建成功") print(f" - field: {facet_result.field}") print(f" - label: {facet_result.label}") print(f" - type: {facet_result.type}") print(f" - values count: {len(facet_result.values)}") def test_search_response_with_facets(): """测试 SearchResponse 与 Facets""" print("\n=== 测试 3: 创建 SearchResponse 对象(包含 Facets)===") # 创建 Facets facets = [ FacetResult( field="categoryName_keyword", label="商品类目", type="terms", values=[ FacetValue(value="玩具", label="玩具", count=100, selected=False), FacetValue(value="益智玩具", label="益智玩具", count=50, selected=False), ] ), FacetResult( field="brandName_keyword", label="品牌", type="terms", values=[ FacetValue(value="乐高", label="乐高", count=80, selected=True), FacetValue(value="美泰", label="美泰", count=60, selected=False), ] ) ] # 创建 SearchResponse response = SearchResponse( hits=[ { "_id": "1", "_score": 10.5, "_source": {"name": "测试商品1"} } ], total=1, max_score=10.5, took_ms=50, facets=facets, query_info={"original_query": "玩具"} ) print(f"✓ SearchResponse 创建成功") print(f" - total: {response.total}") print(f" - facets count: {len(response.facets) if response.facets else 0}") print(f" - facets 类型: {type(response.facets)}") if response.facets: print(f"\n Facet 1:") print(f" - field: {response.facets[0].field}") print(f" - label: {response.facets[0].label}") print(f" - values count: {len(response.facets[0].values)}") print(f" - first value: {response.facets[0].values[0].value} (count: {response.facets[0].values[0].count})") def test_serialization(): """测试序列化和反序列化""" print("\n=== 测试 4: 序列化和反序列化 ===") # 创建带 facets 的响应 facets = [ FacetResult( field="price", label="价格", type="range", values=[ FacetValue(value="0-50", label="0-50元", count=30, selected=False), FacetValue(value="50-100", label="50-100元", count=45, selected=True), ] ) ] response = SearchResponse( hits=[], total=0, max_score=0.0, took_ms=10, facets=facets, query_info={} ) # 序列化为字典 response_dict = response.model_dump() print(f"✓ 序列化为字典成功") print(f" - facets 类型: {type(response_dict['facets'])}") print(f" - facets 内容: {response_dict['facets']}") # 序列化为 JSON response_json = response.model_dump_json() print(f"\n✓ 序列化为 JSON 成功") print(f" - JSON 长度: {len(response_json)} 字符") print(f" - JSON 片段: {response_json[:200]}...") # 从 JSON 反序列化 response_from_json = SearchResponse.model_validate_json(response_json) print(f"\n✓ 从 JSON 反序列化成功") print(f" - facets 恢复: {len(response_from_json.facets) if response_from_json.facets else 0} 个") if response_from_json.facets: print(f" - 第一个 facet field: {response_from_json.facets[0].field}") print(f" - 第一个 facet values: {len(response_from_json.facets[0].values)} 个") def test_pydantic_auto_conversion(): """测试 Pydantic 是否能自动从字典转换(这是原来的方式)""" print("\n=== 测试 5: Pydantic 自动转换(字典 -> 模型)===") # 使用字典创建 SearchResponse(测试 Pydantic 的自动转换能力) facets_dict = [ { "field": "categoryName_keyword", "label": "商品类目", "type": "terms", "values": [ { "value": "玩具", "label": "玩具", "count": 100, "selected": False } ] } ] try: response = SearchResponse( hits=[], total=0, max_score=0.0, took_ms=10, facets=facets_dict, # 传入字典而不是 FacetResult 对象 query_info={} ) print(f"✓ Pydantic 可以从字典自动转换") print(f" - facets 类型: {type(response.facets)}") print(f" - facets[0] 类型: {type(response.facets[0])}") print(f" - 是否为 FacetResult: {isinstance(response.facets[0], FacetResult)}") except Exception as e: print(f"✗ Pydantic 自动转换失败: {e}") def main(): """运行所有测试""" print("开始测试 Facets 修复...\n") try: test_facet_models() test_search_response_with_facets() test_serialization() test_pydantic_auto_conversion() print("\n" + "="*60) print("✅ 所有测试通过!") print("="*60) print("\n总结:") print("1. FacetValue 和 FacetResult 模型创建正常") print("2. SearchResponse 可以正确接收 FacetResult 对象列表") print("3. 序列化和反序列化工作正常") print("4. Pydantic 可以自动将字典转换为模型(但我们现在直接使用模型更好)") return 0 except Exception as e: print(f"\n❌ 测试失败: {e}") import traceback traceback.print_exc() return 1 if __name__ == "__main__": exit(main())