d3a4e259
tangwang
相关文档
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
<!-- 2bec2252-690d-478e-9ce8-bc9073ec23ae c3f51467-b81b-47b7-869f-3da700299e26 -->
# API响应格式优化与SPU索引重构
## 概述
重构搜索系统以实现:
1. 外部接口友好的API响应格式(移除ES内部格式 `_hits`, `_source`, `_score`)
2. SPU维度的索引结构(包含嵌套variants数组)
3. 所有客户共用同一索引(使用tenant_id隔离)
4. 配置简化(完全移除MySQL相关配置,只保留ES搜索配置)
5. 创建base配置(店匠通用配置)和SPU数据导入流程
## 核心设计原则
- **配置只关注ES搜索**:配置文件只包含ES字段定义、查询域、排序规则等搜索相关配置
- **数据灌入流程写死**:数据来源和转换逻辑由Pipeline层(脚本)决定,不在配置中体现
- **代码简洁无冗余**:不做向后兼容,直接删除不需要的代码
## 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级别字段定义**:
- `tenant_id` (KEYWORD, required)
- `product_id` (对应SPU的id)
- `title_zh`, `title_en` (多语言标题)
- `description_zh`, `description_en` (多语言描述)
- `min_price`, `max_price`, `compare_at_price` (扁平化价格)
- `vendor`, `product_type`, `tags` 等
- **嵌套variants字段定义**:
- `variants` (nested type)
- variants包含:`variant_id`, `title`, `price`, `sku`, `stock`, `options` 等
### 1.2 移除配置中的MySQL相关字段
**文件**: [`config/config_loader.py`](config/config_loader.py)
修改:
|
ae5a294d
tangwang
命名修改、代码清理
|
47
|
- **删除** `TenantConfig` 中的 `mysql_config`, `main_table`, `extension_table` 字段定义
|
d3a4e259
tangwang
相关文档
|
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
|
- **删除** `_parse_config` 中解析这些字段的代码
- **删除** `_parse_field_config` 中解析 `source_table`, `source_column` 的代码
- 保持其他配置解析逻辑不变
**文件**: [`config/field_types.py`](config/field_types.py)
修改:
- **删除** `FieldConfig` 中的 `source_table`, `source_column` 字段定义
- 保持其他字段类型定义不变
### 1.3 更新配置验证
**文件**: [`config/config_loader.py`](config/config_loader.py)
修改:
- 添加 `tenant_id` 字段验证(必需字段)
- 移除所有与MySQL/数据源相关的验证逻辑
## Phase 2: 索引结构重构(SPU维度)
### 2.1 更新Mapping生成器
**文件**: [`indexer/mapping_generator.py`](indexer/mapping_generator.py)
修改:
- 在 `_generate_mappings` 中:
- 添加 `tenant_id` 字段(KEYWORD, required)
- 支持嵌套 `variants` 字段(nested type)
- 支持扁平化价格字段(`min_price`, `max_price`, `compare_at_price`)
- 确保所有字段映射正确生成
### 2.2 创建SPU数据转换器
**文件**: [`indexer/spu_transformer.py`](indexer/spu_transformer.py) (NEW)
创建SPU数据转换器(**不依赖配置中的source_table/source_column**):
- **数据读取**:直接从MySQL读取 `shoplazza_product_spu` 和 `shoplazza_product_sku` 表(写死在代码中)
- **数据聚合**:按 `spu_id` 和 `tenant_id` 关联,将SKU数据聚合为variants数组
- **字段映射**:将SPU和SKU表的字段映射到ES文档字段(写死在代码中)
- **价格计算**:计算 `min_price`, `max_price`, `compare_at_price`
- **向量生成**:支持文本和图片向量生成(复用现有encoder)
- **文档生成**:生成SPU级别的ES文档,包含嵌套variants数组
- **tenant_id注入**:自动注入 `tenant_id` 字段
### 2.3 创建店匠数据导入脚本
**文件**: [`scripts/ingest_shoplazza.py`](scripts/ingest_shoplazza.py) (NEW)
创建店匠数据导入脚本:
- 连接MySQL数据库(连接信息通过参数或环境变量传入)
- 读取 `shoplazza_product_spu` 和 `shoplazza_product_sku` 表
- 使用SPU转换器转换数据
- 批量导入到ES索引 `search_products`
- 支持 `--tenant-id` 参数(必需)
- 支持 `--recreate` 参数(重建索引)
- 支持 `--batch-size` 参数
## Phase 3: API响应格式重构
### 3.1 更新响应模型
**文件**: [`api/models.py`](api/models.py)
修改:
- **创建** `VariantResult` 模型:
- `variant_id`, `title`, `price`, `sku`, `stock`, `options` 等
- **创建** `ProductResult` 模型:
- `product_id`, `title`, `handle`, `description`, `vendor`, `product_type`, `tags`
- `price`, `compare_at_price`, `currency`, `image_url`, `in_stock`
- `variants` (List[VariantResult])
- `relevance_score` (float, 0-1)
- **修改** `SearchResponse` 模型:
- 将 `hits` 改为 `results` (List[ProductResult])
- 添加 `suggestions` (List[str])
- 添加 `related_searches` (List[str])
- 保持 `facets`, `total`, `took_ms` 等字段
### 3.2 创建结果格式化器
**文件**: [`api/result_formatter.py`](api/result_formatter.py) (NEW)
创建结果格式化器:
- **方法** `format_search_results(es_hits, max_score) -> List[ProductResult]`:
- 将ES返回的 `_hits` 格式转换为 `ProductResult` 列表
- 提取SPU级别字段(从 `_source` 中提取)
- 提取嵌套variants数组(从 `_source.variants` 中提取)
- 计算 `relevance_score`(从 `_score` 归一化到0-1,基于max_score)
- 处理缺失字段(提供默认值)
- **方法** `format_facets(es_aggregations, facet_configs) -> List[FacetResult]`:
- 格式化facets结果(保持现有逻辑)
- **方法** `generate_suggestions(query, results) -> List[str]`:
- 生成搜索建议(暂时返回空数组)
- **方法** `generate_related_searches(query, results) -> List[str]`:
- 生成相关搜索(暂时返回空数组)
### 3.3 更新搜索器
**文件**: [`search/searcher.py`](search/searcher.py)
修改:
- **添加** `tenant_id` 参数到 `search` 方法(必需)
- **修改** 查询构建:在filter中添加 `tenant_id` 过滤(必需)
- **修改** 结果处理:
- 使用 `ResultFormatter` 格式化结果
- 返回 `results` 而不是 `hits`
- 移除ES内部格式字段(`_id`, `_score`, `_source`)
- **修改** `SearchResult` 类:
- 将 `hits` 改为 `results` (List[ProductResult])
- 添加 `suggestions` 和 `related_searches` 字段
### 3.4 更新API路由
**文件**: [`api/routes/search.py`](api/routes/search.py)
修改:
- **添加** `tenant_id` 参数获取:
- 优先从请求头 `X-Tenant-ID` 获取
- 其次从查询参数 `tenant_id` 获取
- 如果都没有,返回400错误
- **修改** 搜索调用:
- 传递 `tenant_id` 给 `searcher.search()`
- **修改** 响应构建:
- 使用格式化后的 `results`
- 添加 `suggestions` 和 `related_searches`(暂时返回空数组)
## Phase 4: DataTransformer重构
|
ae5a294d
tangwang
命名修改、代码清理
|
184
|
### 4.1 重构DataTransformer(向后兼容,用于tenant1)
|
d3a4e259
tangwang
相关文档
|
185
186
187
188
189
|
**文件**: [`indexer/data_transformer.py`](indexer/data_transformer.py)
修改:
|
ae5a294d
tangwang
命名修改、代码清理
|
190
|
- **保持** 现有逻辑(用于tenant1等旧配置)
|
d3a4e259
tangwang
相关文档
|
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
|
- **添加** 检查:如果 `field.source_column` 不存在,跳过该字段(向后兼容)
- **注意**:base配置不使用DataTransformer,使用SPU转换器
## Phase 5: 测试数据生成
### 5.1 创建测试数据生成脚本
**文件**: [`scripts/generate_test_data.py`](scripts/generate_test_data.py) (NEW)
创建测试数据生成脚本:
- 生成100条SPU测试数据(符合 `shoplazza_product_spu` 表结构)
- 为每个SPU生成1-5个SKU变体(符合 `shoplazza_product_sku` 表结构)
- 包含中文和英文标题
- 包含价格、库存、图片等字段
- 输出为MySQL INSERT语句或CSV文件
- 设置 `tenant_id` 为指定值
### 5.2 创建数据导入脚本
**文件**: [`scripts/import_test_data.py`](scripts/import_test_data.py) (NEW)
创建数据导入脚本:
- 连接MySQL数据库
- 导入测试数据到 `shoplazza_product_spu` 和 `shoplazza_product_sku` 表
- 设置 `tenant_id` 为base客户的ID(如 "base" 或 "1")
- 验证数据导入结果
## Phase 6: 测试脚本和文档
### 6.1 创建测试脚本
**文件**: [`scripts/test_base.py`](scripts/test_base.py) (NEW)
创建base配置测试脚本:
- 测试数据导入(使用ingest_shoplazza.py)
- 测试搜索API(验证tenant_id过滤)
- 测试多语言搜索
- 测试facets聚合
- **验证响应格式**:
- 确认返回 `results` 而不是 `hits`
- 确认每个result包含 `product_id`, `title`, `variants`, `relevance_score`
- 确认variants数组格式正确
- 确认没有ES内部格式字段(`_id`, `_score`, `_source`)
### 6.2 创建说明文档
**文件**: [`docs/BASE_CONFIG_GUIDE.md`](docs/BASE_CONFIG_GUIDE.md) (NEW)
创建base配置测试指南:
- 数据导入步骤
- 配置说明(强调不包含MySQL配置)
- API测试示例(包含tenant_id参数)
- 响应格式说明
- 常见问题解答
## Phase 7: 更新设计文档
### 7.1 更新设计文档
**文件**: [`设计文档.md`](设计文档.md)
修改:
- 更新索引结构说明(SPU维度,所有客户共用 `search_products` 索引)
- 更新配置说明(完全移除MySQL相关配置,只保留ES搜索配置)
- 更新API响应格式说明(results格式,非hits格式)
- 更新数据导入流程说明(Pipeline层决定数据源,配置不包含数据源信息)
- 添加base配置说明
- 添加tenant_id隔离说明
## 关键修改点总结
1. **配置系统**:
- 完全移除 `mysql_config`, `main_table`, `extension_table`, `source_table`, `source_column`
- 配置只包含ES搜索相关配置
- 代码简洁,无冗余,无向后兼容逻辑
2. **数据转换**:
- SPU转换器直接从MySQL读取,不依赖配置
- 数据映射逻辑写死在代码中
- 支持嵌套variants数组
3. **索引结构**:
- SPU级别索引
- 嵌套variants字段
- tenant_id字段(必需)
4. **API响应**:
- 从 `hits` 改为 `results`
- 从 `_id`, `_score`, `_source` 改为 `product_id`, `relevance_score`, 结构化字段
- 包含 `variants` 数组
5. **租户隔离**:
- 所有客户共用 `search_products` 索引
- 使用 `tenant_id` 字段过滤
- API必须提供 `tenant_id` 参数
### To-dos
- [ ] Create ResponseTransformer to convert ES hits to Shoplazza format (results, facets, suggestions, related_searches)
- [ ] Update API models: add VariantOption, ProductVariant, ProductResult, update SearchResponse with new format
- [ ] Update search route to use ResponseTransformer and return Shoplazza format
|
ae5a294d
tangwang
命名修改、代码清理
|
302
303
|
- [ ] Create script to generate 100 SPU+SKU test records for tenant2 in Shoplazza tables
- [ ] Create tenant2 config.yaml with search-only fields (no pipeline details)
|
d3a4e259
tangwang
相关文档
|
304
|
- [ ] Create or update SPUDataTransformer to join SPU+SKU and create nested variants structure
|
ae5a294d
tangwang
命名修改、代码清理
|
305
306
|
- [ ] Create tenant2 ingestion script that loads from MySQL and uses SPU transformer
- [ ] Create test script and documentation for tenant2 setup and testing
|
d3a4e259
tangwang
相关文档
|
307
|
- [ ] Update design document: SPU-level indexing, unified index, config separation, pipeline decisions
|