分面数据问题根源和解决方案.md 6.24 KB

分面数据问题根源和解决方案

📊 诊断结果总结

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的categorycategory_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行)

修改内容

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

运行检查

python scripts/check_data_source.py --tenant-id 162 --db-host <host> ...

关键检查

  • category字段是否有值
  • 如果有值,值的格式是什么(是否包含"/")
  • 如果也为空,说明Excel导入映射有问题

步骤2:重新导入数据到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

步骤3:验证ES数据

运行ES数据检查脚本

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.categorycategory_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数据是否正确,分面是否能正常显示