# 分面数据问题根源和解决方案 ## 📊 诊断结果总结 ### MySQL数据情况 - **总SPU数**:11254 - **category_path字段**:只有1个有值(ID列表格式),11253个为空 - **option表数据**: - 有option定义的SPU:886个 - position=1, name='color': 885个 ✅ - position=2, name='size': 885个 ✅ - position=3, name='material': 885个 ✅ ### ES索引数据情况 - **总文档数**:10000 - **category1_name字段**:只有1个有值(ID列表格式),其他都是None ❌ - **specifications聚合查询**:有数据 ✅ - specifications.color: Beige: 1226, Khaki: 1176等 - specifications.size: 1: 1234, 12: 1234等 - specifications.material: 塑料英文包装: 17277等 ## 🔍 问题根源 ### 问题1:category1_name 几乎都为空 **数据流分析**: 1. **Excel生成阶段**(`csv_to_excel_multi_variant.py`): - Excel字段:`'专辑名称': csv_data['categoryName']` - 从CSV的`categoryName`字段读取,应该有值 2. **Excel导入店匠 → MySQL**: - Excel的"专辑名称"字段 → 可能映射到MySQL的`category`或`category_path`字段 - **问题**:店匠系统可能将"专辑名称"映射到`category`字段,而不是`category_path` - 诊断结果显示:`category_path`几乎都是空的 3. **MySQL → ES转换**(`spu_transformer.py`): - 原逻辑:只从`category_path`解析`category1_name` - 如果`category_path`为空,`category1_name`不会被设置 - **已修复**:如果`category_path`为空,使用`category`字段作为备选(第241-259行) **关键检查点**: - MySQL的`category`字段是否有值? - 如果`category`字段也为空,说明Excel导入时"专辑名称"没有正确映射 ### 问题2:specifications分面查询无结果 **奇怪的现象**: - ES聚合查询显示有数据(Beige: 1226, Khaki: 1176等) - 但前端显示为空 **可能原因**: 1. **前端搜索时有查询条件**: - 如果搜索时添加了查询条件(如`query="手机"`),ES会先过滤文档 - 过滤后的文档可能没有specifications数据,导致聚合结果为空 - **需要验证**:不带查询条件的搜索,分面是否有数据 2. **分面聚合构建或解析问题**: - 前端请求:`["category1_name", "specifications.color", "specifications.size", "specifications.material"]` - ES构建的聚合名称:`specifications_color_facet` - 前端解析时的字段匹配:`specifications.color` - **需要验证**:`format_facets`函数是否正确匹配 3. **tenant_id过滤问题**: - 如果tenant_id不匹配,会导致没有匹配的文档 ## ✅ 已实施的修复 ### 修复1:支持从category字段生成category1_name **文件**:`indexer/spu_transformer.py`(第241-259行) **修改内容**: ```python elif pd.notna(spu_row.get('category')): # 如果category_path为空,使用category字段作为category1_name的备选 category = str(spu_row['category']) # 从category字段解析多级分类 if '/' in category: path_parts = category.split('/') if len(path_parts) > 0: doc['category1_name'] = path_parts[0].strip() else: # 直接作为category1_name doc['category1_name'] = category.strip() ``` **说明**:如果MySQL的`category`字段有值,修复后的代码应该能生成`category1_name` ## 🔧 需要执行的操作 ### 步骤1:检查MySQL的category字段 **更新诊断脚本**(已更新):`scripts/check_data_source.py` **运行检查**: ```bash python scripts/check_data_source.py --tenant-id 162 --db-host ... ``` **关键检查**: - `category`字段是否有值 - 如果有值,值的格式是什么(是否包含"/") - 如果也为空,说明Excel导入映射有问题 ### 步骤2:重新导入数据到ES **修复代码后,需要重新导入数据**: ```bash python scripts/recreate_and_import.py \ --tenant-id 162 \ --db-host \ --db-database saas \ --db-username saas \ --db-password \ --es-host http://localhost:9200 ``` ### 步骤3:验证ES数据 **运行ES数据检查脚本**: ```bash python scripts/check_es_data.py --tenant-id 162 ``` **检查内容**: - `category1_name`字段是否有值 - `specifications`字段是否有数据 - 分面聚合查询是否有结果 ## 📝 数据流程说明 ### Excel生成 → MySQL **Excel字段**(`csv_to_excel_multi_variant.py`): - `'专辑名称': csv_data['categoryName']` - 分类信息 - `'款式1': 'color'`(M行)- 选项名称 - `'款式2': 'size'`(M行)- 选项名称 - `'款式3': 'material'`(M行)- 选项名称 - `'款式1': 'Red'`(P行)- 选项值 - `'款式2': '5'`(P行)- 选项值 - `'款式3': '塑料'`(P行)- 选项值 **Excel导入店匠 → MySQL映射**(需要确认): - `'专辑名称'` → `shoplazza_product_spu.category` 或 `category_path` - `'款式1/2/3'`(M行)→ `shoplazza_product_option.name` + `position` - `'款式1/2/3'`(P行)→ `shoplazza_product_sku.option1/2/3` ### MySQL → ES转换 **当前逻辑**(`spu_transformer.py`): 1. **category1_name生成**: - 优先从`category_path`解析(第228-240行) - 如果`category_path`为空,从`category`字段解析(第241-259行)✅ 已修复 2. **specifications生成**(第351-370行): - 从`option表`获取name(position → name映射) - 从`SKU表`获取option1/2/3值 - 构建`specifications`数组 **关键点**: - 需要确保MySQL的`category`字段有值 - 需要确保`option表`有数据且`name`是英文(color/size/material) - 需要确保SKU的`option1/2/3`字段有值 ## 🎯 关键发现 1. **specifications数据是存在的**:ES聚合查询能正常返回color/size/material的分面数据 2. **category1_name几乎都是空的**:这是因为`category_path`为空,需要从`category`字段生成 3. **需要重新导入数据**:修复代码后,需要重新导入数据到ES才能生效 ## 🔄 下一步 1. ✅ **代码已修复**:支持从`category`字段生成`category1_name` 2. ⏳ **需要检查MySQL数据**:确认`category`字段是否有值 3. ⏳ **需要重新导入数据**:将修复后的数据导入ES 4. ⏳ **需要验证**:检查ES数据是否正确,分面是否能正常显示