# API响应格式优化与SPU索引重构 ## 概述 重构搜索系统以支持: 1. 外部接口友好的API响应格式(移除ES内部格式) 2. SPU维度的索引结构(包含嵌套variants数组) 3. 所有客户共用同一索引(使用tenant_id隔离) 4. 配置简化(移除MySQL相关配置,只保留ES搜索配置) 5. 添加新客户(tenant2)测试数据和配置 ## Phase 1: 配置文件重构 ### 1.1 创建BASE配置文件 **文件**: [`config/schema/base/config.yaml`](config/schema/base/config.yaml) (NEW) 创建通用配置文件,所有使用店匠表的客户共用: - 移除 `mysql_config`, `main_table`, `extension_table`, `source_table`, `source_column` - 固定索引名称:`search_products` - SPU级别字段定义(包含嵌套variants) - 必需字段:`tenant_id` (KEYWORD, required) - 扁平化价格字段:`min_price`, `max_price`, `compare_at_price` - 多语言字段:`title_zh`, `title_en`, `description_zh`, `description_en` 等 - 嵌套variants结构定义 ### 1.2 创建tenant2配置文件 **文件**: [`config/schema/tenant2/config.yaml`](config/schema/tenant2/config.yaml) (NEW) 基于BASE配置,为tenant2创建配置文件: - 继承BASE配置结构 - 定义tenant2特定的字段和搜索域 - 支持多语言(中文、英文) ### 1.3 更新配置加载器 **文件**: [`config/config_loader.py`](config/config_loader.py) 修改: - 移除 `mysql_config`, `main_table`, `extension_table` 解析 - 移除字段配置中的 `source_table`, `source_column` 解析 - 固定 `es_index_name` 为 `search_products` - 添加 `tenant_id` 字段验证(必需字段) - 支持嵌套字段配置(variants) ### 1.4 更新字段类型定义 **文件**: [`config/field_types.py`](config/field_types.py) 修改: - 移除 `FieldConfig` 中的 `source_table`, `source_column` - 添加嵌套字段支持(nested fields) - 添加扁平化价格字段类型 ## Phase 2: 索引结构重构(SPU维度) ### 2.1 更新Mapping生成器 **文件**: [`indexer/mapping_generator.py`](indexer/mapping_generator.py) 修改: - 生成SPU级别的mapping - 添加 `tenant_id` 字段(KEYWORD, required) - 添加嵌套 `variants` 字段(nested type) - 添加扁平化价格字段(`min_price`, `max_price`, `compare_at_price`) - 移除SKU级别的字段映射 ### 2.2 创建SPU数据转换器 **文件**: [`indexer/spu_transformer.py`](indexer/spu_transformer.py) (NEW) 创建SPU数据转换器: - 从MySQL读取SPU和SKU数据 - 按SPU聚合SKU数据为variants数组 - 计算扁平化价格字段(min_price, max_price, compare_at_price) - 生成SPU级别的ES文档 - 注入 `tenant_id` 字段 ### 2.3 更新数据导入脚本 **文件**: [`scripts/ingest_shoplazza.py`](scripts/ingest_shoplazza.py) (NEW) 创建店匠数据导入脚本: - 从MySQL读取 `shoplazza_product_spu` 和 `shoplazza_product_sku` 表 - 按 `spu_id` 和 `tenant_id` 关联数据 - 使用SPU转换器转换数据 - 批量导入到ES索引 `search_products` - 支持 `--tenant-id` 参数 ## Phase 3: API响应格式重构 ### 3.1 更新响应模型 **文件**: [`api/models.py`](api/models.py) 修改 `SearchResponse` 模型: - 将 `hits` 改为 `results` (List[ProductResult]) - 添加 `ProductResult` 模型(包含product_id, title, variants, relevance_score等) - 添加 `VariantResult` 模型(包含variant_id, title, price, sku等) - 保持 `facets` 格式 - 添加 `suggestions` 和 `related_searches` 字段(暂时返回空数组) ### 3.2 创建结果转换器 **文件**: [`api/result_formatter.py`](api/result_formatter.py) (NEW) 创建结果格式化器: - 将ES返回的 `_hits` 格式转换为外部接口格式 - 提取SPU级别字段 - 提取嵌套variants数组 - 计算 `relevance_score`(从 `_score` 转换) - 格式化facets结果 - 生成suggestions和related_searches(暂时返回空数组) ### 3.3 更新搜索器 **文件**: [`search/searcher.py`](search/searcher.py) 修改: - 在搜索查询中添加 `tenant_id` 过滤(必需) - 更新结果处理逻辑,使用结果格式化器 - 移除ES内部格式字段(`_id`, `_score`, `_source`) - 返回格式化的外部接口格式 ### 3.4 更新API路由 **文件**: [`api/routes/search.py`](api/routes/search.py) 修改: - 添加 `tenant_id` 参数(从请求头或查询参数获取) - 在搜索请求中添加 `tenant_id` 过滤 - 使用结果格式化器格式化响应 - 返回新的响应格式 ## Phase 4: 测试数据生成 ### 4.1 创建测试数据生成脚本 **文件**: [`scripts/generate_test_data.py`](scripts/generate_test_data.py) (NEW) 创建测试数据生成脚本: - 生成100条SPU测试数据 - 为每个SPU生成1-5个SKU变体 - 包含中文和英文标题 - 包含价格、库存、图片等字段 - 输出为MySQL INSERT语句或CSV文件 ### 4.2 创建数据导入脚本 **文件**: [`scripts/import_test_data.py`](scripts/import_test_data.py) (NEW) 创建数据导入脚本: - 连接MySQL数据库 - 导入测试数据到 `shoplazza_product_spu` 和 `shoplazza_product_sku` 表 - 设置 `tenant_id` 为tenant2的ID - 验证数据导入结果 ## Phase 5: 测试脚本和文档 ### 5.1 创建测试脚本 **文件**: [`scripts/test_tenant2.py`](scripts/test_tenant2.py) (NEW) 创建tenant2测试脚本: - 测试数据导入 - 测试搜索API - 测试多语言搜索 - 测试facets聚合 - 验证响应格式 ### 5.2 创建说明文档 **文件**: [`docs/TENANT2_TEST_GUIDE.md`](docs/TENANT2_TEST_GUIDE.md) (NEW) 创建tenant2测试指南: - 数据导入步骤 - 配置说明 - API测试示例 - 常见问题解答 ## Phase 6: 更新设计文档 ### 6.1 更新设计文档 **文件**: [`设计文档.md`](设计文档.md) 修改: - 更新索引结构说明(SPU维度,所有客户共用) - 更新配置说明(移除MySQL相关配置) - 更新API响应格式说明 - 更新数据导入流程说明 - 添加tenant2测试说明 ## 关键修改点 1. **索引结构**: - 索引名称:`search_products`(所有客户共用) - 索引粒度:SPU级别 - 租户隔离:使用 `tenant_id` 字段过滤 - 嵌套结构:`variants` 数组包含SKU数据 2. **配置简化**: - 移除 `mysql_config`, `main_table`, `extension_table` - 移除字段配置中的 `source_table`, `source_column` - 只保留ES搜索相关配置 3. **API响应格式**: - 从 `_hits`, `_source`, `_score` 改为 `results`, `product_id`, `title`, `relevance_score` - 添加 `variants` 数组 - 添加 `suggestions` 和 `related_searches`(暂时返回空数组) 4. **数据导入**: - 从MySQL读取SPU和SKU数据 - 按SPU聚合SKU数据 - 生成SPU级别的ES文档 - 注入 `tenant_id` 字段 ### To-dos - [ ] 创建BASE配置文件(config/schema/base/config.yaml),移除MySQL相关配置,定义SPU级别字段和嵌套variants结构 - [ ] 创建tenant2配置文件(config/schema/tenant2/config.yaml),基于BASE配置定义tenant2特定字段 - [ ] 更新配置加载器(config/config_loader.py),移除MySQL相关配置解析,支持嵌套字段和tenant_id验证 - [ ] 更新字段类型定义(config/field_types.py),移除source_table和source_column,添加嵌套字段支持 - [ ] 更新Mapping生成器(indexer/mapping_generator.py),生成SPU级别mapping,添加tenant_id和嵌套variants字段 - [ ] 创建SPU数据转换器(indexer/spu_transformer.py),从MySQL读取SPU和SKU数据,按SPU聚合为variants数组 - [ ] 创建店匠数据导入脚本(scripts/ingest_shoplazza.py),支持从MySQL导入SPU和SKU数据到ES - [ ] 更新响应模型(api/models.py),添加ProductResult和VariantResult模型,修改SearchResponse格式 - [ ] 创建结果格式化器(api/result_formatter.py),将ES返回格式转换为外部接口友好格式 - [ ] 更新搜索器(search/searcher.py),添加tenant_id过滤,使用结果格式化器格式化响应 - [ ] 更新API路由(api/routes/search.py),添加tenant_id参数,返回新的响应格式 - [ ] 创建测试数据生成脚本(scripts/generate_test_data.py),生成100条SPU测试数据 - [ ] 创建数据导入脚本(scripts/import_test_data.py),导入测试数据到MySQL - [ ] 创建tenant2测试脚本(scripts/test_tenant2.py),测试数据导入和搜索API - [ ] 创建tenant2测试指南(docs/TENANT2_TEST_GUIDE.md),包含数据导入步骤和API测试示例 - [ ] 更新设计文档(设计文档.md),更新索引结构、配置说明和API响应格式说明