分面数据问题诊断.md
7.97 KB
分面数据问题诊断报告
问题描述
前端显示的分面结果都是空的:
- Category: 空
- Color: 空
- Size: 空
- Material: 空
ES的聚合查询结果也是空的。
数据流程分析
1. 数据生成阶段(csv_to_excel_multi_variant.py)
生成的数据:
分类信息:
- Excel字段:
'专辑名称': csv_data['categoryName'] - 示例值:
"电子产品"或"服装/男装"(从CSV的categoryName字段读取)
属性信息(M+P类型商品):
- Excel字段(M行主商品):
'款式1': 'color'(选项名称)'款式2': 'size'(选项名称)'款式3': 'material'(选项名称)
- Excel字段(P行子款式):
'款式1': 'Red'(选项值,从COLORS列表随机选择)'款式2': '5'(选项值,1-30随机选择)'款式3': '塑料'(选项值,从商品标题提取)
2. Excel导入店匠系统 → MySQL
预期映射:
分类字段:
- Excel
'专辑名称'→ MySQLshoplazza_product_spu.category_path或category字段 - 问题:店匠系统可能将"专辑名称"映射到
category字段,而不是category_path字段
属性字段:
- Excel
'款式1/2/3'(M行)→ MySQLshoplazza_product_option.name和position - Excel
'款式1/2/3'(P行)→ MySQLshoplazza_product_sku.option1/2/3
3. MySQL → ES转换阶段(spu_transformer.py)
category1_name 构建逻辑(第228-240行):
if pd.notna(spu_row.get('category_path')):
category_path = str(spu_row['category_path'])
# 解析category_path获取多层级分类名称
path_parts = category_path.split('/')
if len(path_parts) > 0:
doc['category1_name'] = path_parts[0].strip()
问题:如果MySQL中的category_path字段为空,category1_name不会被设置!
specifications 构建逻辑(第328-347行):
# 构建option名称映射(position -> name)
option_name_map = {}
if not options.empty:
for _, opt_row in options.iterrows():
position = opt_row.get('position')
name = opt_row.get('name')
if pd.notna(position) and pd.notna(name):
option_name_map[int(position)] = str(name)
# 构建specifications
if pd.notna(sku_row.get('option1')) and 1 in option_name_map:
specifications.append({
'sku_id': sku_id,
'name': option_name_map[1], # 使用option表的name字段
'value': str(sku_row['option1'])
})
问题:如果shoplazza_product_option表中没有记录,或者name字段值不是英文(如"color"),会导致:
option_name_map为空,无法构建specifications- 即使有值,如果name不是"color"/"size"/"material",前端也无法正确匹配
问题根源
问题1:category1_name 为空
原因:
- MySQL的
category_path字段可能为空 - Excel的"专辑名称"可能被映射到
category字段而不是category_path - 如果
category_path为空,category1_name不会被设置
验证方法:
SELECT COUNT(*) as total,
COUNT(category_path) as has_category_path,
COUNT(category) as has_category
FROM shoplazza_product_spu
WHERE tenant_id = 162 AND deleted = 0;
问题2:specifications 为空
原因:
shoplazza_product_option表可能没有数据- option表的
name字段值可能不是英文(不是"color"、"size"、"material")
验证方法:
SELECT DISTINCT name, position, COUNT(*) as count
FROM shoplazza_product_option
WHERE tenant_id = 162 AND deleted = 0
GROUP BY name, position
ORDER BY position, name;
解决方案
方案1:修复 spu_transformer.py - 支持从category字段生成category1_name
修改indexer/spu_transformer.py的_transform_spu_to_doc方法,如果category_path为空,使用category字段作为备选:
# Category相关字段
if pd.notna(spu_row.get('category_path')):
category_path = str(spu_row['category_path'])
doc['category_path_zh'] = category_path
doc['category_path_en'] = None
# 解析category_path获取多层级分类名称
path_parts = category_path.split('/')
if len(path_parts) > 0:
doc['category1_name'] = path_parts[0].strip()
if len(path_parts) > 1:
doc['category2_name'] = path_parts[1].strip()
if len(path_parts) > 2:
doc['category3_name'] = path_parts[2].strip()
elif pd.notna(spu_row.get('category')):
# 如果category_path为空,使用category字段作为category1_name
category = str(spu_row['category'])
doc['category1_name'] = category.strip()
# 如果category包含"/",也尝试解析
if '/' in category:
path_parts = category.split('/')
if len(path_parts) > 0:
doc['category1_name'] = path_parts[0].strip()
if len(path_parts) > 1:
doc['category2_name'] = path_parts[1].strip()
if len(path_parts) > 2:
doc['category3_name'] = path_parts[2].strip()
方案2:检查并修复 option 表的 name 字段值
需要确保shoplazza_product_option表的name字段值是英文:
- position=1 的name应该是
"color" - position=2 的name应该是
"size" - position=3 的name应该是
"material"
如果值不对,需要更新:
-- 查看当前的name值
SELECT DISTINCT name, position
FROM shoplazza_product_option
WHERE tenant_id = 162 AND deleted = 0
ORDER BY position;
-- 如果需要更新(示例)
-- UPDATE shoplazza_product_option
-- SET name = CASE position
-- WHEN 1 THEN 'color'
-- WHEN 2 THEN 'size'
-- WHEN 3 THEN 'material'
-- END
-- WHERE tenant_id = 162 AND deleted = 0;
方案3:验证数据完整性
使用诊断脚本检查数据:
python scripts/check_data_source.py \
--tenant-id 162 \
--db-host <mysql_host> \
--db-port 3316 \
--db-database saas \
--db-username saas \
--db-password <password>
诊断步骤
步骤1:检查MySQL数据
运行诊断脚本:
cd /home/tw/SearchEngine
source /home/tw/miniconda3/etc/profile.d/conda.sh
conda activate searchengine
python scripts/check_data_source.py --tenant-id 162 --db-host <host> --db-database saas --db-username saas --db-password <password>
步骤2:根据检查结果修复
如果 category_path 为空:
- 使用方案1:修改
spu_transformer.py支持从category字段生成category1_name
如果 option 表没有数据或name值不对:
- 检查Excel导入是否正确
- 如果需要,手动更新option表的name字段值
步骤3:重新导入数据到ES
python scripts/recreate_and_import.py \
--tenant-id 162 \
--db-host <host> \
--db-database saas \
--db-username saas \
--db-password <password> \
--es-host http://localhost:9200
步骤4:验证ES数据
检查ES索引中的文档:
curl -X GET "http://localhost:9200/search_products/_search?pretty" -H 'Content-Type: application/json' -d'
{
"query": {
"term": {
"tenant_id": "162"
}
},
"size": 1,
"_source": ["spu_id", "title_zh", "category1_name", "specifications", "option1_name"]
}'
预期结果
修复后,ES文档应该包含:
category1_name字段:
{ "category1_name": "电子产品" }specifications字段:
{ "specifications": [ {"sku_id": "123", "name": "color", "value": "Red"}, {"sku_id": "123", "name": "size", "value": "5"}, {"sku_id": "123", "name": "material", "value": "塑料"} ] }option1_name/2_name/3_name字段:
{ "option1_name": "color", "option2_name": "size", "option3_name": "material" }
总结
问题可能出现在:
- MySQL数据层面:
category_path字段为空,或者shoplazza_product_option表没有正确的数据 - 数据转换层面:
spu_transformer.py没有处理category_path为空的情况
建议先运行诊断脚本检查MySQL数据,然后根据检查结果进行修复。