分面问题修复总结.md 4.7 KB

分面数据问题修复总结

问题现象

前端显示的分面结果都是空的:

  • Category: 空
  • Color: 空
  • Size: 空
  • Material: 空

ES的聚合查询结果也是空的。

问题分析

数据流程

  1. 数据生成(csv_to_excel_multi_variant.py):

    • 生成Excel文件,包含"专辑名称"(分类)和"款式1/2/3"(属性名称和值)
  2. Excel导入店匠 → MySQL:

    • "专辑名称" → 可能映射到 categorycategory_path 字段
    • "款式1/2/3"(M行)→ shoplazza_product_option.name
    • "款式1/2/3"(P行)→ shoplazza_product_sku.option1/2/3
  3. MySQL → ES转换(spu_transformer.py):

    • category1_namecategory_path 解析
    • specificationsoption表.name + sku表.option1/2/3 构建

根本原因

  1. category1_name 为空

    • MySQL的category_path字段可能为空
    • Excel的"专辑名称"可能被映射到category字段而不是category_path
    • 原代码只从category_path解析,如果为空则category1_name不会被设置
  2. specifications 为空

    • shoplazza_product_option表可能没有数据
    • name字段值不是英文(不是"color"、"size"、"material")

已实施的修复

修复1:支持从category字段生成category1_name

文件: indexer/spu_transformer.py

修改内容

  • 如果category_path为空,使用category字段作为备选
  • category字段解析多级分类(如果包含"/")
  • 如果category不包含"/",直接作为category1_name

代码位置:第241-259行

elif pd.notna(spu_row.get('category')):
    # 如果category_path为空,使用category字段作为category1_name的备选
    category = str(spu_row['category'])
    doc['category_name_zh'] = category
    doc['category_name_en'] = None
    doc['category_name'] = category

    # 尝试从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()
    else:
        # 如果category不包含"/",直接作为category1_name
        doc['category1_name'] = category.strip()

诊断工具

已创建诊断脚本:scripts/check_data_source.py

使用方法

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 <mysql_host> \
    --db-port 3316 \
    --db-database saas \
    --db-username saas \
    --db-password <password>

检查内容

  1. SPU汇总信息
  2. category_path 字段是否有值
  3. option 表的 name 字段值
  4. SKU 表的 option1/2/3 字段值

下一步操作

步骤1:运行诊断脚本检查MySQL数据

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

步骤2:根据检查结果修复数据

如果 option 表的 name 值不对:

检查option表的name字段值:

SELECT DISTINCT name, position
FROM shoplazza_product_option
WHERE tenant_id = 162 AND deleted = 0
ORDER BY position;

如果需要,更新为英文:

  • position=1 的 name 应该是 "color"
  • position=2 的 name 应该是 "size"
  • position=3 的 name 应该是 "material"

步骤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索引中的文档是否包含:

  • category1_name 字段
  • specifications 字段(包含color、size、material)
  • option1_nameoption2_nameoption3_name 字段
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", "option2_name", "option3_name"]
}'

预期结果

修复后,ES文档应该包含:

{
  "spu_id": "123",
  "title_zh": "商品标题",
  "category1_name": "电子产品",
  "specifications": [
    {"sku_id": "456", "name": "color", "value": "Red"},
    {"sku_id": "456", "name": "size", "value": "5"},
    {"sku_id": "456", "name": "material", "value": "塑料"}
  ],
  "option1_name": "color",
  "option2_name": "size",
  "option3_name": "material"
}

前端分面应该能正常显示分类和属性值。