Commit ae5a294d3f93b6542de1831d70c239f2213e1145

Authored by tangwang
1 parent 37e994bb

命名修改、代码清理

.cursor/plans/API响应格式优化与SPU索引重构.2.md
... ... @@ -9,7 +9,7 @@
9 9 2. SPU维度的索引结构(包含嵌套variants数组)
10 10 3. 所有客户共用同一索引(使用tenant_id隔离)
11 11 4. 配置简化(移除MySQL相关配置,只保留ES搜索配置)
12   -5. 添加新客户(customer2)测试数据和配置
  12 +5. 添加新客户(tenant2)测试数据和配置
13 13  
14 14 ## Phase 1: 配置文件重构
15 15  
... ... @@ -27,14 +27,14 @@
27 27 - 多语言字段:`title_zh`, `title_en`, `description_zh`, `description_en` 等
28 28 - 嵌套variants结构定义
29 29  
30   -### 1.2 创建customer2配置文件
  30 +### 1.2 创建tenant2配置文件
31 31  
32   -**文件**: [`config/schema/customer2/config.yaml`](config/schema/customer2/config.yaml) (NEW)
  32 +**文件**: [`config/schema/tenant2/config.yaml`](config/schema/tenant2/config.yaml) (NEW)
33 33  
34   -基于BASE配置,为customer2创建配置文件:
  34 +基于BASE配置,为tenant2创建配置文件:
35 35  
36 36 - 继承BASE配置结构
37   -- 定义customer2特定的字段和搜索域
  37 +- 定义tenant2特定的字段和搜索域
38 38 - 支持多语言(中文、英文)
39 39  
40 40 ### 1.3 更新配置加载器
... ... @@ -168,16 +168,16 @@
168 168  
169 169 - 连接MySQL数据库
170 170 - 导入测试数据到 `shoplazza_product_spu` 和 `shoplazza_product_sku` 表
171   -- 设置 `tenant_id` 为customer2的ID
  171 +- 设置 `tenant_id` 为tenant2的ID
172 172 - 验证数据导入结果
173 173  
174 174 ## Phase 5: 测试脚本和文档
175 175  
176 176 ### 5.1 创建测试脚本
177 177  
178   -**文件**: [`scripts/test_customer2.py`](scripts/test_customer2.py) (NEW)
  178 +**文件**: [`scripts/test_tenant2.py`](scripts/test_tenant2.py) (NEW)
179 179  
180   -创建customer2测试脚本:
  180 +创建tenant2测试脚本:
181 181  
182 182 - 测试数据导入
183 183 - 测试搜索API
... ... @@ -187,9 +187,9 @@
187 187  
188 188 ### 5.2 创建说明文档
189 189  
190   -**文件**: [`docs/CUSTOMER2_TEST_GUIDE.md`](docs/CUSTOMER2_TEST_GUIDE.md) (NEW)
  190 +**文件**: [`docs/TENANT2_TEST_GUIDE.md`](docs/TENANT2_TEST_GUIDE.md) (NEW)
191 191  
192   -创建customer2测试指南:
  192 +创建tenant2测试指南:
193 193  
194 194 - 数据导入步骤
195 195 - 配置说明
... ... @@ -208,7 +208,7 @@
208 208 - 更新配置说明(移除MySQL相关配置)
209 209 - 更新API响应格式说明
210 210 - 更新数据导入流程说明
211   -- 添加customer2测试说明
  211 +- 添加tenant2测试说明
212 212  
213 213 ## 关键修改点
214 214  
... ... @@ -241,7 +241,7 @@
241 241 ### To-dos
242 242  
243 243 - [ ] 创建BASE配置文件(config/schema/base/config.yaml),移除MySQL相关配置,定义SPU级别字段和嵌套variants结构
244   -- [ ] 创建customer2配置文件(config/schema/customer2/config.yaml),基于BASE配置定义customer2特定字段
  244 +- [ ] 创建tenant2配置文件(config/schema/tenant2/config.yaml),基于BASE配置定义tenant2特定字段
245 245 - [ ] 更新配置加载器(config/config_loader.py),移除MySQL相关配置解析,支持嵌套字段和tenant_id验证
246 246 - [ ] 更新字段类型定义(config/field_types.py),移除source_table和source_column,添加嵌套字段支持
247 247 - [ ] 更新Mapping生成器(indexer/mapping_generator.py),生成SPU级别mapping,添加tenant_id和嵌套variants字段
... ... @@ -253,6 +253,6 @@
253 253 - [ ] 更新API路由(api/routes/search.py),添加tenant_id参数,返回新的响应格式
254 254 - [ ] 创建测试数据生成脚本(scripts/generate_test_data.py),生成100条SPU测试数据
255 255 - [ ] 创建数据导入脚本(scripts/import_test_data.py),导入测试数据到MySQL
256   -- [ ] 创建customer2测试脚本(scripts/test_customer2.py),测试数据导入和搜索API
257   -- [ ] 创建customer2测试指南(docs/CUSTOMER2_TEST_GUIDE.md),包含数据导入步骤和API测试示例
  256 +- [ ] 创建tenant2测试脚本(scripts/test_tenant2.py),测试数据导入和搜索API
  257 +- [ ] 创建tenant2测试指南(docs/TENANT2_TEST_GUIDE.md),包含数据导入步骤和API测试示例
258 258 - [ ] 更新设计文档(设计文档.md),更新索引结构、配置说明和API响应格式说明
259 259 \ No newline at end of file
... ...
.cursor/plans/API响应格式优化与SPU索引重构.4.md
... ... @@ -44,7 +44,7 @@
44 44  
45 45 修改:
46 46  
47   -- **删除** `CustomerConfig` 中的 `mysql_config`, `main_table`, `extension_table` 字段定义
  47 +- **删除** `TenantConfig` 中的 `mysql_config`, `main_table`, `extension_table` 字段定义
48 48 - **删除** `_parse_config` 中解析这些字段的代码
49 49 - **删除** `_parse_field_config` 中解析 `source_table`, `source_column` 的代码
50 50 - 保持其他配置解析逻辑不变
... ... @@ -181,13 +181,13 @@
181 181  
182 182 ## Phase 4: DataTransformer重构
183 183  
184   -### 4.1 重构DataTransformer(向后兼容,用于customer1)
  184 +### 4.1 重构DataTransformer(向后兼容,用于tenant1)
185 185  
186 186 **文件**: [`indexer/data_transformer.py`](indexer/data_transformer.py)
187 187  
188 188 修改:
189 189  
190   -- **保持** 现有逻辑(用于customer1等旧配置)
  190 +- **保持** 现有逻辑(用于tenant1等旧配置)
191 191 - **添加** 检查:如果 `field.source_column` 不存在,跳过该字段(向后兼容)
192 192 - **注意**:base配置不使用DataTransformer,使用SPU转换器
193 193  
... ... @@ -299,9 +299,9 @@
299 299 - [ ] Create ResponseTransformer to convert ES hits to Shoplazza format (results, facets, suggestions, related_searches)
300 300 - [ ] Update API models: add VariantOption, ProductVariant, ProductResult, update SearchResponse with new format
301 301 - [ ] Update search route to use ResponseTransformer and return Shoplazza format
302   -- [ ] Create script to generate 100 SPU+SKU test records for customer2 in Shoplazza tables
303   -- [ ] Create customer2 config.yaml with search-only fields (no pipeline details)
  302 +- [ ] Create script to generate 100 SPU+SKU test records for tenant2 in Shoplazza tables
  303 +- [ ] Create tenant2 config.yaml with search-only fields (no pipeline details)
304 304 - [ ] Create or update SPUDataTransformer to join SPU+SKU and create nested variants structure
305   -- [ ] Create customer2 ingestion script that loads from MySQL and uses SPU transformer
306   -- [ ] Create test script and documentation for customer2 setup and testing
  305 +- [ ] Create tenant2 ingestion script that loads from MySQL and uses SPU transformer
  306 +- [ ] Create test script and documentation for tenant2 setup and testing
307 307 - [ ] Update design document: SPU-level indexing, unified index, config separation, pipeline decisions
308 308 \ No newline at end of file
... ...
.cursor/plans/API响应格式优化与SPU索引重构.5.最终执行.md
... ... @@ -54,7 +54,7 @@
54 54  
55 55 修改:
56 56  
57   -- **删除** `CustomerConfig` 中的 `mysql_config`, `main_table`, `extension_table` 字段定义
  57 +- **删除** `TenantConfig` 中的 `mysql_config`, `main_table`, `extension_table` 字段定义
58 58 - **删除** `_parse_config` 中解析这些字段的代码
59 59 - **删除** `_parse_field_config` 中解析 `source_table`, `source_column` 的代码
60 60 - 保持其他配置解析逻辑不变
... ... @@ -191,13 +191,13 @@
191 191  
192 192 ## Phase 4: DataTransformer重构
193 193  
194   -### 4.1 重构DataTransformer(向后兼容,用于customer1)
  194 +### 4.1 重构DataTransformer(向后兼容,用于tenant1)
195 195  
196 196 **文件**: [`indexer/data_transformer.py`](indexer/data_transformer.py)
197 197  
198 198 修改:
199 199  
200   -- **保持** 现有逻辑(用于customer1等旧配置)
  200 +- **保持** 现有逻辑(用于tenant1等旧配置)
201 201 - **添加** 检查:如果 `field.source_column` 不存在,跳过该字段(向后兼容)
202 202 - **注意**:base配置不使用DataTransformer,使用SPU转换器
203 203  
... ... @@ -309,9 +309,9 @@
309 309 - [ ] Create ResponseTransformer to convert ES hits to Shoplazza format (results, facets, suggestions, related_searches)
310 310 - [ ] Update API models: add VariantOption, ProductVariant, ProductResult, update SearchResponse with new format
311 311 - [ ] Update search route to use ResponseTransformer and return Shoplazza format
312   -- [ ] Create script to generate 100 SPU+SKU test records for customer2 in Shoplazza tables
313   -- [ ] Create customer2 config.yaml with search-only fields (no pipeline details)
  312 +- [ ] Create script to generate 100 SPU+SKU test records for tenant2 in Shoplazza tables
  313 +- [ ] Create tenant2 config.yaml with search-only fields (no pipeline details)
314 314 - [ ] Create or update SPUDataTransformer to join SPU+SKU and create nested variants structure
315   -- [ ] Create customer2 ingestion script that loads from MySQL and uses SPU transformer
316   -- [ ] Create test script and documentation for customer2 setup and testing
  315 +- [ ] Create tenant2 ingestion script that loads from MySQL and uses SPU transformer
  316 +- [ ] Create test script and documentation for tenant2 setup and testing
317 317 - [ ] Update design document: SPU-level indexing, unified index, config separation, pipeline decisions
318 318 \ No newline at end of file
... ...
.cursor/plans/API响应格式优化与SPU索引重构.纠正.md
... ... @@ -8,7 +8,7 @@
8 8 2. SPU维度的索引结构(包含嵌套variants数组)
9 9 3. 所有客户共用同一索引(使用tenant_id隔离)
10 10 4. 配置简化(移除MySQL相关配置,只保留ES搜索配置)
11   -5. 添加新客户(customer2)测试数据和配置
  11 +5. 添加新客户(tenant2)测试数据和配置
12 12  
13 13 ## Phase 1: 配置文件重构
14 14  
... ... @@ -27,8 +27,8 @@
27 27 - 嵌套variants结构定义
28 28  
29 29 务必注意:对于店匠的店铺,我们应该都通用的用base配置即可,不需要另外单独针对某个店铺新建一套配置,也就是所有店匠的商品都用这个base配置。
30   -但是允许有其他某个深度定制客户有自己的索引,比如当前有一套索引customer1,我们不用动他,他的数据灌入流程是另外一份,写死的,他的索引配置也是另外一份。也就是我们的搜索服务可以支持多种配置,索引结构变了、字段变了,就是多一分配置,只是店匠多数用户都用base配置即可。
31   -下面,如果有用到 customer2 的,应该就是指base客户,并注意帮我纠正。
  30 +但是允许有其他某个深度定制客户有自己的索引,比如当前有一套索引tenant1,我们不用动他,他的数据灌入流程是另外一份,写死的,他的索引配置也是另外一份。也就是我们的搜索服务可以支持多种配置,索引结构变了、字段变了,就是多一分配置,只是店匠多数用户都用base配置即可。
  31 +下面,如果有用到 tenant2 的,应该就是指base客户,并注意帮我纠正。
32 32  
33 33 ### 1.3 更新配置加载器
34 34  
... ... @@ -161,16 +161,16 @@
161 161  
162 162 - 连接MySQL数据库
163 163 - 导入测试数据到 `shoplazza_product_spu` 和 `shoplazza_product_sku` 表
164   -- 设置 `tenant_id` 为customer2的ID
  164 +- 设置 `tenant_id` 为tenant2的ID
165 165 - 验证数据导入结果
166 166  
167 167 ## Phase 5: 测试脚本和文档
168 168  
169 169 ### 5.1 创建测试脚本
170 170  
171   -**文件**: [`scripts/test_customer2.py`](scripts/test_customer2.py) (NEW)
  171 +**文件**: [`scripts/test_tenant2.py`](scripts/test_tenant2.py) (NEW)
172 172  
173   -创建customer2测试脚本:
  173 +创建tenant2测试脚本:
174 174  
175 175 - 测试数据导入
176 176 - 测试搜索API
... ... @@ -180,9 +180,9 @@
180 180  
181 181 ### 5.2 创建说明文档
182 182  
183   -**文件**: [`docs/CUSTOMER2_TEST_GUIDE.md`](docs/CUSTOMER2_TEST_GUIDE.md) (NEW)
  183 +**文件**: [`docs/TENANT2_TEST_GUIDE.md`](docs/TENANT2_TEST_GUIDE.md) (NEW)
184 184  
185   -创建customer2测试指南:
  185 +创建tenant2测试指南:
186 186  
187 187 - 数据导入步骤
188 188 - 配置说明
... ... @@ -201,7 +201,7 @@
201 201 - 更新配置说明(移除MySQL相关配置)
202 202 - 更新API响应格式说明
203 203 - 更新数据导入流程说明
204   -- 添加customer2测试说明
  204 +- 添加tenant2测试说明
205 205  
206 206 ## 关键修改点
207 207  
... ...
.cursor/plans/API响应格式优化与SPU索引重构3.md
... ... @@ -28,7 +28,7 @@
28 28 - 多语言字段:`title_zh`, `title_en`, `description_zh`, `description_en` 等
29 29 - 嵌套variants结构定义
30 30  
31   -**注意**:店匠的店铺都使用base配置,不需要单独配置。允许其他深度定制客户(如customer1)有自己的配置。
  31 +**注意**:店匠的店铺都使用base配置,不需要单独配置。允许其他深度定制客户(如tenant1)有自己的配置。
32 32  
33 33 ### 1.2 更新配置加载器
34 34  
... ... @@ -244,9 +244,9 @@
244 244 - [ ] Create ResponseTransformer to convert ES hits to Shoplazza format (results, facets, suggestions, related_searches)
245 245 - [ ] Update API models: add VariantOption, ProductVariant, ProductResult, update SearchResponse with new format
246 246 - [ ] Update search route to use ResponseTransformer and return Shoplazza format
247   -- [ ] Create script to generate 100 SPU+SKU test records for customer2 in Shoplazza tables
248   -- [ ] Create customer2 config.yaml with search-only fields (no pipeline details)
  247 +- [ ] Create script to generate 100 SPU+SKU test records for tenant2 in Shoplazza tables
  248 +- [ ] Create tenant2 config.yaml with search-only fields (no pipeline details)
249 249 - [ ] Create or update SPUDataTransformer to join SPU+SKU and create nested variants structure
250   -- [ ] Create customer2 ingestion script that loads from MySQL and uses SPU transformer
251   -- [ ] Create test script and documentation for customer2 setup and testing
  250 +- [ ] Create tenant2 ingestion script that loads from MySQL and uses SPU transformer
  251 +- [ ] Create test script and documentation for tenant2 setup and testing
252 252 - [ ] Update design document: SPU-level indexing, unified index, config separation, pipeline decisions
253 253 \ No newline at end of file
... ...
.cursor/plans/es-query-25a9f060.plan.检索表达式优化.ES_function表达式.md
... ... @@ -245,7 +245,7 @@ if enable_rerank and self.rerank_engine.enabled:
245 245 )
246 246 ```
247 247  
248   -#### `/home/tw/SearchEngine/config/schema/customer1/config.yaml`
  248 +#### `/home/tw/SearchEngine/config/schema/tenant1/config.yaml`
249 249  
250 250 **添加配置项**(254行后):
251 251  
... ... @@ -274,7 +274,7 @@ function_score:
274 274 weight: 1.1
275 275 ```
276 276  
277   -#### `/home/tw/SearchEngine/config/customer_config.py`
  277 +#### `/home/tw/SearchEngine/config/tenant_config.py`
278 278  
279 279 **更新配置类**:
280 280  
... ... @@ -293,7 +293,7 @@ class FunctionScoreConfig:
293 293 functions: List[Dict[str, Any]] = field(default_factory=list)
294 294  
295 295 @dataclass
296   -class CustomerConfig:
  296 +class TenantConfig:
297 297 # ... 其他字段 ...
298 298 ranking: RankingConfig # 保留用于兼容
299 299 rerank: RerankConfig # 新增
... ...
.cursor/plans/es-query-25a9f060.plan.检索表达式优化.ES_function表达式.基于ES_fuction_score原生能力优化.md
... ... @@ -30,7 +30,7 @@
30 30  
31 31 ## 配置设计(简化版)
32 32  
33   -### `/home/tw/SearchEngine/config/schema/customer1/config.yaml`
  33 +### `/home/tw/SearchEngine/config/schema/tenant1/config.yaml`
34 34  
35 35 ```yaml
36 36 # Function Score配置(ES层打分规则)
... ... @@ -131,7 +131,7 @@ rerank:
131 131  
132 132 ### 1. 定义配置模型
133 133  
134   -**文件**: `/home/tw/SearchEngine/config/models.py`(新建或更新customer_config.py)
  134 +**文件**: `/home/tw/SearchEngine/config/models.py`(新建或更新tenant_config.py)
135 135  
136 136 ```python
137 137 from dataclasses import dataclass, field
... ... @@ -282,7 +282,7 @@ if fs_config and fs_config.max_boost:
282 282  
283 283 ### 4. 更新示例配置
284 284  
285   -**文件**: `/home/tw/SearchEngine/config/schema/customer1/config.yaml`
  285 +**文件**: `/home/tw/SearchEngine/config/schema/tenant1/config.yaml`
286 286  
287 287 在 `ranking` 配置后添加新配置(参见上面完整YAML)
288 288  
... ...
.cursor/plans/将数据pipeline相关配置从索引配置中剥离.md
... ... @@ -3,7 +3,7 @@
3 3  
4 4 ## Overview
5 5  
6   -Implement clean separation between **Search Configuration** (customer-facing, ES/search focused) and **Data Pipeline** (internal ETL, script-controlled). Configuration files will only contain search engine settings, while data source and transformation logic will be controlled entirely by script parameters.
  6 +Implement clean separation between **Search Configuration** (tenant-facing, ES/search focused) and **Data Pipeline** (internal ETL, script-controlled). Configuration files will only contain search engine settings, while data source and transformation logic will be controlled entirely by script parameters.
7 7  
8 8 ## Phase 1: Configuration File Cleanup
9 9  
... ... @@ -22,7 +22,7 @@ Implement clean separation between **Search Configuration** (customer-facing, ES
22 22  
23 23 **Keep** (search configuration):
24 24  
25   -- `customer_name`
  25 +- `tenant_name`
26 26 - `es_index_name`
27 27 - `es_settings`
28 28 - `fields` (simplified, no source mapping)
... ... @@ -49,7 +49,7 @@ fields:
49 49  
50 50 ### 1.2 Update Legacy Configuration
51 51  
52   -**File**: [`config/schema/customer1_legacy/config.yaml`](config/schema/customer1_legacy/config.yaml)
  52 +**File**: [`config/schema/tenant1_legacy/config.yaml`](config/schema/tenant1_legacy/config.yaml)
53 53  
54 54 Apply same cleanup as BASE config, marking it as legacy in comments.
55 55  
... ... @@ -101,7 +101,7 @@ class TransformerFactory:
101 101 @staticmethod
102 102 def create(
103 103 transformer_type: str, # 'sku' or 'spu'
104   - config: CustomerConfig,
  104 + config: TenantConfig,
105 105 text_encoder=None,
106 106 image_encoder=None
107 107 ) -> BaseDataTransformer:
... ... @@ -247,9 +247,9 @@ Changes:
247 247 - Simplify field parsing (no source mapping)
248 248 - Keep validation of ES/search related config
249 249  
250   -### 4.2 Update CustomerConfig Model
  250 +### 4.2 Update TenantConfig Model
251 251  
252   -**File**: [`config/__init__.py`](config/**init**.py) or wherever CustomerConfig is defined
  252 +**File**: [`config/__init__.py`](config/**init**.py) or wherever TenantConfig is defined
253 253  
254 254 Remove attributes:
255 255  
... ... @@ -377,7 +377,7 @@ Add deprecation warnings to scripts that still use old config format.
377 377  
378 378 ### 1. Separation of Concerns
379 379  
380   -**Search Configuration** (customer-facing):
  380 +**Search Configuration** (tenant-facing):
381 381  
382 382 - What fields exist in ES
383 383 - How fields are analyzed/indexed
... ... @@ -445,7 +445,7 @@ Pipeline decisions (transformer, data source, field mapping) made at runtime, no
445 445  
446 446 ✅ **Configuration reusability across data sources**
447 447  
448   -✅ **Customer doesn't need to understand ETL**
  448 +✅ **Tenant doesn't need to understand ETL**
449 449  
450 450 ✅ **Easier to add new data sources**
451 451  
... ...
.cursor/plans/所有tenant按同一份所有_返回接口优化.md
... ... @@ -142,10 +142,10 @@ New models:
142 142  
143 143 ## Phase 6: Legacy Migration
144 144  
145   -### 6.1 Rename Customer1 to Legacy
  145 +### 6.1 Rename Tenant1 to Legacy
146 146  
147   -- Rename [`config/schema/customer1/`](config/schema/customer1/) to [`config/schema/customer1_legacy/`](config/schema/customer1_legacy/)
148   -- Update config to use old index `search_customer1` (preserve for backward compatibility)
  147 +- Rename [`config/schema/tenant1/`](config/schema/tenant1/) to [`config/schema/tenant1_legacy/`](config/schema/tenant1_legacy/)
  148 +- Update config to use old index `search_tenant1` (preserve for backward compatibility)
149 149 - Mark as deprecated in comments
150 150  
151 151 ### 6.2 Update Scripts for BASE
... ... @@ -159,7 +159,7 @@ New models:
159 159  
160 160 **Files**: [`frontend/`](frontend/) HTML/JS files
161 161  
162   -- Change index name references from `search_customer1` to `search_products`
  162 +- Change index name references from `search_tenant1` to `search_products`
163 163 - Use BASE config endpoints
164 164 - Archive old frontend as `frontend_legacy/` if needed
165 165  
... ... @@ -205,7 +205,7 @@ Updates:
205 205 - **API响应格式**: 采用 Shoplazza 标准格式
206 206 - **Price扁平化**: 说明高频字段的性能优化策略
207 207 - **Nested变体**: 详细说明 variants 数组结构
208   -- **Legacy配置**: customer1等为遗留配置,仅用于兼容
  208 +- **Legacy配置**: tenant1等为遗留配置,仅用于兼容
209 209  
210 210 ### 8.2 Create BASE Guide
211 211  
... ... @@ -258,7 +258,7 @@ Steps:
258 258  
259 259 ### BASE Configuration Philosophy
260 260  
261   -**BASE = Universal Standard**: All new merchants use BASE config with Shoplazza tables. No per-customer schema customization. Customization happens through:
  261 +**BASE = Universal Standard**: All new merchants use BASE config with Shoplazza tables. No per-tenant schema customization. Customization happens through:
262 262  
263 263 - Configuration parameters (analyzers, function_score, etc.)
264 264 - Extension tables (if needed for additional fields)
... ... @@ -280,7 +280,7 @@ High-frequency operations (filtering, sorting) on price require optimal performa
280 280 ### Legacy vs BASE
281 281  
282 282 - **BASE**: New standard, all future merchants
283   -- **Legacy (customer1_legacy)**: Deprecated, exists only for backward compatibility
  283 +- **Legacy (tenant1_legacy)**: Deprecated, exists only for backward compatibility
284 284 - All scripts/frontend default to BASE
285 285 - Legacy access requires explicit suffix (`_legacy`)
286 286  
... ... @@ -291,12 +291,12 @@ High-frequency operations (filtering, sorting) on price require optimal performa
291 291 - [ ] Add NESTED field type support to field_types.py and mapping generator
292 292 - [ ] Create SPU-level data transformer that joins SPU+SKU tables and creates nested variant array
293 293 - [ ] Create script to generate 100 realistic SPU+SKU test records in Shoplazza tables
294   -- [ ] Create customer2 configuration using unified schema and Shoplazza tables only
295   -- [ ] Create customer2 ingestion script that loads from MySQL Shoplazza tables
  294 +- [ ] Create tenant2 configuration using unified schema and Shoplazza tables only
  295 +- [ ] Create tenant2 ingestion script that loads from MySQL Shoplazza tables
296 296 - [ ] Update query builder to support tenant_id filtering and nested variant queries
297 297 - [ ] Create response transformer to convert ES format to Shoplazza-compatible format
298 298 - [ ] Update API models with new Shoplazza response format (ProductResult, variants, suggestions, etc.)
299 299 - [ ] Update search routes to use response transformer and return new format
300   -- [ ] Migrate customer1 configuration to unified schema and SPU-level indexing
301   -- [ ] Create customer2 guide, update design docs, API docs, and create migration guide
302   -- [ ] Create comprehensive test script for customer2 with data generation, ingestion, and search validation
303 300 \ No newline at end of file
  301 +- [ ] Migrate tenant1 configuration to unified schema and SPU-level indexing
  302 +- [ ] Create tenant2 guide, update design docs, API docs, and create migration guide
  303 +- [ ] Create comprehensive test script for tenant2 with data generation, ingestion, and search validation
304 304 \ No newline at end of file
... ...
.cursor/plans/所有租户共用一套统一配置.tenantID只在请求层级.服务层级没有tenantID相关的独立配置.md
... ... @@ -6,7 +6,7 @@
6 6 将搜索服务从按租户启动改造为真正的多租户架构:
7 7  
8 8 - 服务启动时不指定租户ID,所有租户共用一套配置
9   -- 删除customer1配置,去掉base层级,统一为config.yaml
  9 +- 删除tenant1配置,去掉base层级,统一为config.yaml
10 10 - 统一脚本接口:启动、停止、重启、数据灌入
11 11 - 统一数据灌入流程,ES只有一份索引
12 12 - 前端支持在搜索框左侧输入租户ID
... ... @@ -18,30 +18,30 @@
18 18 **文件**: `config/config.yaml` (NEW)
19 19  
20 20 - 将 `config/schema/base/config.yaml` 移动到 `config/config.yaml`
21   -- 删除 `customer_name` 字段(不再需要)
22   -- 删除 `customer_id` 相关逻辑
  21 +- 删除 `tenant_name` 字段(不再需要)
  22 +- 删除 `tenant_id` 相关逻辑
23 23 - 固定索引名称为 `search_products`
24 24 - 确保包含 `tenant_id` 字段(必需)
25 25  
26   -### 1.2 删除customer1配置
  26 +### 1.2 删除tenant1配置
27 27  
28 28 **删除文件**:
29 29  
30   -- `config/schema/customer1/config.yaml`
31   -- `config/schema/customer1/` 目录(如果为空)
  30 +- `config/schema/tenant1/config.yaml`
  31 +- `config/schema/tenant1/` 目录(如果为空)
32 32  
33 33 ### 1.3 更新ConfigLoader
34 34  
35 35 **文件**: `config/config_loader.py`
36 36  
37   -修改 `load_customer_config()` 方法:
  37 +修改 `load_tenant_config()` 方法:
38 38  
39   -- 移除 `customer_id` 参数
  39 +- 移除 `tenant_id` 参数
40 40 - 改为 `load_config()` 方法
41 41 - 直接加载 `config/config.yaml`
42   -- 移除对 `config/schema/{customer_id}/config.yaml` 的查找逻辑
43   -- 移除 `customer_id` 字段验证
44   -- 更新 `CustomerConfig` 类:移除 `customer_id` 字段
  42 +- 移除对 `config/schema/{tenant_id}/config.yaml` 的查找逻辑
  43 +- 移除 `tenant_id` 字段验证
  44 +- 更新 `TenantConfig` 类:移除 `tenant_id` 字段
45 45  
46 46 ### 1.4 更新配置验证
47 47  
... ... @@ -50,7 +50,7 @@
50 50 修改 `validate_config()` 方法:
51 51  
52 52 - 确保 `tenant_id` 字段存在且为必需
53   -- 移除对 `customer_id` 的验证
  53 +- 移除对 `tenant_id` 的验证
54 54  
55 55 ## Phase 2: 服务启动改造
56 56  
... ... @@ -60,14 +60,14 @@
60 60  
61 61 修改 `init_service()` 方法:
62 62  
63   -- 移除 `customer_id` 参数
  63 +- 移除 `tenant_id` 参数
64 64 - 直接加载统一配置(`config/config.yaml`)
65   -- 移除 `CUSTOMER_ID` 环境变量依赖
66   -- 更新日志输出(不再显示customer_id)
  65 +- 移除 `TENANT_ID` 环境变量依赖
  66 +- 更新日志输出(不再显示tenant_id)
67 67  
68 68 修改 `startup_event()` 方法:
69 69  
70   -- 移除 `CUSTOMER_ID` 环境变量读取
  70 +- 移除 `TENANT_ID` 环境变量读取
71 71 - 直接调用 `init_service()` 不传参数
72 72  
73 73 ### 2.2 更新main.py
... ... @@ -76,8 +76,8 @@
76 76  
77 77 修改 `cmd_serve()` 方法:
78 78  
79   -- 移除 `--customer` 参数
80   -- 移除 `CUSTOMER_ID` 环境变量设置
  79 +- 移除 `--tenant` 参数
  80 +- 移除 `TENANT_ID` 环境变量设置
81 81 - 更新帮助信息
82 82  
83 83 ### 2.3 更新启动脚本
... ... @@ -86,16 +86,16 @@
86 86  
87 87 修改:
88 88  
89   -- 移除 `CUSTOMER_ID` 环境变量
90   -- 移除 `--customer` 参数
  89 +- 移除 `TENANT_ID` 环境变量
  90 +- 移除 `--tenant` 参数
91 91 - 简化启动命令
92 92  
93 93 **文件**: `scripts/start_servers.py`
94 94  
95 95 修改 `start_api_server()` 方法:
96 96  
97   -- 移除 `customer` 参数
98   -- 移除 `CUSTOMER_ID` 环境变量设置
  97 +- 移除 `tenant` 参数
  98 +- 移除 `TENANT_ID` 环境变量设置
99 99 - 简化启动命令
100 100  
101 101 ## Phase 3: 脚本体系统一
... ... @@ -139,7 +139,7 @@
139 139 功能:
140 140  
141 141 - 从MySQL读取数据
142   -- 转换数据格式(统一处理base和customer1数据源)
  142 +- 转换数据格式(统一处理base和tenant1数据源)
143 143 - 灌入到ES索引 `search_products`
144 144 - 支持指定租户ID过滤数据
145 145 - 自动处理字段映射:缺失字段随机生成,多余字段忽略
... ... @@ -204,7 +204,7 @@
204 204  
205 205 - 移除 `--config` 参数(不再需要)
206 206 - 直接加载统一配置(`config/config.yaml`)
207   -- 统一处理所有数据源(不再区分base和customer1)
  207 +- 统一处理所有数据源(不再区分base和tenant1)
208 208 - 支持 `--tenant-id` 参数过滤数据
209 209 - 字段映射逻辑:
210 210 - 如果字段在配置中但数据源中没有,随机生成
... ... @@ -217,7 +217,7 @@
217 217  
218 218 修改:
219 219  
220   -- 移除对配置中 `customer_id` 的依赖
  220 +- 移除对配置中 `tenant_id` 的依赖
221 221 - 统一处理所有数据源
222 222 - 确保字段映射正确(缺失字段随机生成,多余字段忽略)
223 223  
... ... @@ -299,8 +299,8 @@
299 299  
300 300 ### 7.1 清理废弃代码
301 301  
302   -- 删除所有对 `customer_id` 的引用
303   -- 删除所有对 `customer1` 配置的引用
  302 +- 删除所有对 `tenant_id` 的引用
  303 +- 删除所有对 `tenant1` 配置的引用
304 304 - 删除所有对 `base` 配置层级的引用
305 305 - 清理不再使用的脚本
306 306  
... ... @@ -316,12 +316,12 @@
316 316  
317 317 ### 需要修改的文件:
318 318  
319   -1. `config/config_loader.py` - 移除customer_id逻辑
  319 +1. `config/config_loader.py` - 移除tenant_id逻辑
320 320 2. `config/config.yaml` - 统一配置文件(从base移动)
321   -3. `api/app.py` - 移除customer_id参数
322   -4. `main.py` - 移除customer参数
323   -5. `scripts/start_backend.sh` - 移除CUSTOMER_ID
324   -6. `scripts/start_servers.py` - 移除customer参数
  321 +3. `api/app.py` - 移除tenant_id参数
  322 +4. `main.py` - 移除tenant参数
  323 +5. `scripts/start_backend.sh` - 移除TENANT_ID
  324 +6. `scripts/start_servers.py` - 移除tenant参数
325 325 7. `scripts/ingest_shoplazza.py` - 统一数据灌入
326 326 8. `frontend/index.html` - 添加租户ID输入框
327 327 9. `frontend/static/js/app_base.js` - 读取租户ID
... ... @@ -329,8 +329,8 @@
329 329  
330 330 ### 需要删除的文件:
331 331  
332   -1. `config/schema/customer1/config.yaml`
333   -2. `config/schema/customer1/` 目录
  332 +1. `config/schema/tenant1/config.yaml`
  333 +2. `config/schema/tenant1/` 目录
334 334 3. `scripts/demo_base.sh`
335 335 4. `scripts/stop_base.sh`
336 336 5. 其他废弃脚本
... ...
.github/workflows/test.yml
... ... @@ -209,7 +209,7 @@ EOF
209 209 - name: Run integration tests
210 210 env:
211 211 ES_HOST: http://localhost:9200
212   - CUSTOMER_ID: test_customer
  212 + TENANT_ID: test_tenant
213 213 TESTING_MODE: true
214 214 run: |
215 215 python -m pytest tests/integration/ \
... ... @@ -312,7 +312,7 @@ EOF
312 312 - name: Start API service
313 313 env:
314 314 ES_HOST: http://localhost:9200
315   - CUSTOMER_ID: test_customer
  315 + TENANT_ID: test_tenant
316 316 API_HOST: 127.0.0.1
317 317 API_PORT: 6003
318 318 TESTING_MODE: true
... ... @@ -320,7 +320,7 @@ EOF
320 320 python -m api.app \
321 321 --host $API_HOST \
322 322 --port $API_PORT \
323   - --customer $CUSTOMER_ID \
  323 + --tenant $TENANT_ID \
324 324 --es-host $ES_HOST &
325 325 echo $! > api.pid
326 326  
... ... @@ -339,7 +339,7 @@ EOF
339 339 ES_HOST: http://localhost:9200
340 340 API_HOST: 127.0.0.1
341 341 API_PORT: 6003
342   - CUSTOMER_ID: test_customer
  342 + TENANT_ID: test_tenant
343 343 TESTING_MODE: true
344 344 run: |
345 345 python -m pytest tests/integration/test_api_integration.py \
... ...
API_DOCUMENTATION.md
... ... @@ -527,7 +527,7 @@ curl "http://localhost:6002/search/12345"
527 527 {
528 528 "status": "healthy",
529 529 "elasticsearch": "connected",
530   - "customer_id": "customer1"
  530 + "tenant_id": "tenant1"
531 531 }
532 532 ```
533 533  
... ... @@ -543,9 +543,9 @@ curl "http://localhost:6002/search/12345"
543 543  
544 544 ```json
545 545 {
546   - "customer_id": "customer1",
547   - "customer_name": "Customer1 Test Instance",
548   - "es_index_name": "search_customer1",
  546 + "tenant_id": "tenant1",
  547 + "tenant_name": "Tenant1 Test Instance",
  548 + "es_index_name": "search_tenant1",
549 549 "num_fields": 20,
550 550 "num_indexes": 4,
551 551 "supported_languages": ["zh", "en", "ru"],
... ... @@ -566,7 +566,7 @@ curl "http://localhost:6002/search/12345"
566 566  
567 567 ```json
568 568 {
569   - "index_name": "search_customer1",
  569 + "index_name": "search_tenant1",
570 570 "document_count": 10000,
571 571 "size_mb": 523.45
572 572 }
... ...
CLAUDE.md
... ... @@ -31,17 +31,17 @@ password: P89cZHS5d7dFyc9R
31 31 ## Architecture
32 32  
33 33 ### Data Flow
34   -1. **Data Source (MySQL)** → Main tables (`shoplazza_product_sku`, `shoplazza_product_spu`) + customer extension tables
  34 +1. **Data Source (MySQL)** → Main tables (`shoplazza_product_sku`, `shoplazza_product_spu`) + tenant extension tables
35 35 2. **Indexer** → Reads from MySQL, applies transformations (embeddings, etc.), writes to Elasticsearch
36 36 3. **Query Parser** → Query rewriting, translation, text embedding conversion
37 37 4. **Searcher** → Executes searches against Elasticsearch with configurable ranking
38 38  
39 39 ### Multi-Tenant Design
40   -Each customer has their own extension table to store custom attributes, multi-language fields (titles, brand names, tags, categories), and business-specific metadata. The main SKU table is joined with customer extension tables during indexing.
  40 +Each tenant has their own extension table to store custom attributes, multi-language fields (titles, brand names, tags, categories), and business-specific metadata. The main SKU table is joined with tenant extension tables during indexing.
41 41  
42 42 ### Configuration System
43 43  
44   -The system uses two types of configurations per customer:
  44 +The system uses two types of configurations per tenant:
45 45  
46 46 1. **Application Structure Config** (`IndexerConfig`) - Defines:
47 47 - Input field mappings from MySQL to Elasticsearch
... ... @@ -89,10 +89,10 @@ The `searcher` supports:
89 89  
90 90 ## Test Data
91 91
92   -**Customer1 Test Dataset:**
93   -- Location: `data/customer1/goods_with_pic.5years_congku.csv.shuf.1w`
  92 +**Tenant1 Test Dataset:**
  93 +- Location: `data/tenant1/goods_with_pic.5years_congku.csv.shuf.1w`
94 94 - Contains 10,000 shuffled product records with images
95   -- Processing script: `data/customer1/task2_process_goods.py`
  95 +- Processing script: `data/tenant1/task2_process_goods.py`
96 96 - Extracts product data from MySQL
97 97 - Maps images from filebank database
98 98 - Creates inverted index (URL → SKU list)
... ... @@ -101,7 +101,7 @@ The `searcher` supports:
101 101  
102 102 1. **Data Sync:** Full data sync from MySQL to Elasticsearch is handled by a separate Java project (not in this repo). This repo may include a simple full-load implementation for testing purposes.
103 103  
104   -2. **Extension Tables:** When designing customer configurations, determine which fields exist in the main SKU table vs. which need to be added to customer-specific extension tables.
  104 +2. **Extension Tables:** When designing tenant configurations, determine which fields exist in the main SKU table vs. which need to be added to tenant-specific extension tables.
105 105  
106 106 3. **Embedding Caching:** For periodic full indexing, embedding results should be cached to avoid recomputation.
107 107  
... ...
DEPLOYMENT.md
... ... @@ -86,7 +86,7 @@ REDIS_PASSWORD=BMfv5aI31kgHWtlx
86 86  
87 87 DEEPL_AUTH_KEY=c9293ab4-ad25-479b-919f-ab4e63b429ed
88 88  
89   -CUSTOMER_ID=customer1
  89 +TENANT_ID=tenant1
90 90 API_HOST=0.0.0.0
91 91 API_PORT=6002
92 92 ```
... ... @@ -146,7 +146,7 @@ from config import ConfigLoader
146 146  
147 147 es_config = get_es_config()
148 148 es_client = ESClient(hosts=[es_config['host']], username=es_config.get('username'), password=es_config.get('password'))
149   -config = ConfigLoader('config/schema').load_customer_config('customer1')
  149 +config = ConfigLoader('config/schema').load_tenant_config('tenant1')
150 150 count = es_client.count(config.es_index_name)
151 151 print(f'Documents in index: {count}')
152 152 "
... ... @@ -255,7 +255,7 @@ kill -9 <PID>
255 255 - 了解所有可用的API端点
256 256  
257 257 3. **自定义配置**
258   - - 编辑 `config/schema/customer1_config.yaml`
  258 + - 编辑 `config/schema/tenant1_config.yaml`
259 259 - 添加查询重写规则
260 260 - 调整ranking表达式
261 261  
... ...
FUNCTION_SCORE_CONFIG_COMPLETE.md
... ... @@ -29,9 +29,9 @@ class RerankConfig:
29 29 description: str = ""
30 30 ```
31 31  
32   -添加到 `CustomerConfig`:
  32 +添加到 `TenantConfig`:
33 33 ```python
34   -class CustomerConfig:
  34 +class TenantConfig:
35 35 # ... 其他字段
36 36 function_score: FunctionScoreConfig
37 37 rerank: RerankConfig
... ... @@ -104,7 +104,7 @@ def _build_score_functions(self) -> List[Dict[str, Any]]:
104 104  
105 105 ### 3. 配置文件示例
106 106  
107   -**文件**: `/home/tw/SearchEngine/config/schema/customer1/config.yaml`
  107 +**文件**: `/home/tw/SearchEngine/config/schema/tenant1/config.yaml`
108 108  
109 109 添加完整的`function_score`配置:
110 110  
... ... @@ -489,7 +489,7 @@ https://www.elastic.co/docs/reference/query-languages/query-dsl/query-dsl-functi
489 489  
490 490 1. **编辑配置文件**
491 491 ```bash
492   -vi config/schema/customer1/config.yaml
  492 +vi config/schema/tenant1/config.yaml
493 493 ```
494 494  
495 495 2. **添加打分规则**
... ...
HighLevelDesign.md
... ... @@ -71,10 +71,10 @@ deleted bit(1)
71 71 ### 测试数据灌入
72 72  
73 73 灌入数据、mysql到ES的自动同步,不在本项目的范围内,另外有java项目负责。
74   -但是,该项目 为了提供测试数据,需要 构造一个实例 customer1.
  74 +但是,该项目 为了提供测试数据,需要 构造一个实例 tenant1.
75 75 我们为他构造一套应用配置和索引配置。
76 76 灌入一批测试数据,可以些一个简单的 全量灌入的实现。
77   -数据源地址在:data/customer1/goods_with_pic.5years_congku.csv.shuf.1w
  77 +数据源地址在:data/tenant1/goods_with_pic.5years_congku.csv.shuf.1w
78 78 请根据这里面的字段,建设辅助表(注意看哪些字段在主表有,哪些需要放到辅表)
79 79 然后写一个程序,将数据分别灌入主表和辅表。
80 80  
... ... @@ -83,7 +83,7 @@ deleted bit(1)
83 83 query分析,做以下几个事情:
84 84  
85 85 1. 查询改写。 配置词典的key是query,value是改写后的查询表达式,比如。比如品牌词 改写为在brand|query OR name|query,类别词、标签词等都可以放进去。纠错、规范化、查询改写等 都可以通过这个词典来配置。
86   -2. 翻译。配置需要得到的几种目标语言。 在customer1测试案例中,我们配置 zh en两种语言。先对query做语言检测,如果query是中文那么要翻译一下en,如果是en那么要翻译zh,如果两者都不是那么zh en都需要翻译。
  86 +2. 翻译。配置需要得到的几种目标语言。 在tenant1测试案例中,我们配置 zh en两种语言。先对query做语言检测,如果query是中文那么要翻译一下en,如果是en那么要翻译zh,如果两者都不是那么zh en都需要翻译。
87 87 3. 如果配置打开了text_embedding查询,并且query 包含了default域的查询,那么要把default域的查询词转向量,后面searcher会用这个向量参与查询。
88 88 翻译代码参考:
89 89 ```
... ...
MULTILANG_FEATURE.md
... ... @@ -14,7 +14,7 @@
14 14  
15 15 ### 字段配置
16 16  
17   -在 `customer1_config.yaml` 中,需要为不同语言的标题字段配置对应的分词器:
  17 +在 `tenant1_config.yaml` 中,需要为不同语言的标题字段配置对应的分词器:
18 18  
19 19 ```yaml
20 20 fields:
... ...
QUICKSTART.md
... ... @@ -24,8 +24,8 @@ export ES_HOST="http://localhost:9200"
24 24 # DeepL API (for translation)
25 25 export DEEPL_API_KEY="your-api-key-here"
26 26  
27   -# Customer ID
28   -export CUSTOMER_ID="customer1"
  27 +# Tenant ID
  28 +export TENANT_ID="tenant1"
29 29 ```
30 30  
31 31 ## Running the System
... ... @@ -37,8 +37,8 @@ export CUSTOMER_ID="customer1"
37 37 docker run -d -p 9200:9200 -e "discovery.type=single-node" elasticsearch:8.11.0
38 38  
39 39 # 2. Ingest sample data (100 documents for quick test)
40   -cd data/customer1
41   -python ingest_customer1.py \
  40 +cd data/tenant1
  41 +python ingest_tenant1.py \
42 42 --limit 100 \
43 43 --recreate-index \
44 44 --es-host http://localhost:9200 \
... ... @@ -61,8 +61,8 @@ curl -X POST http://localhost:6002/search/ \
61 61 docker run -d -p 9200:9200 -e "discovery.type=single-node" -e "ES_JAVA_OPTS=-Xms4g -Xmx4g" elasticsearch:8.11.0
62 62  
63 63 # 2. Ingest full dataset with embeddings (requires GPU, takes ~10-30 min)
64   -cd data/customer1
65   -python ingest_customer1.py \
  64 +cd data/tenant1
  65 +python ingest_tenant1.py \
66 66 --csv goods_with_pic.5years_congku.csv.shuf.1w \
67 67 --recreate-index \
68 68 --batch-size 100 \
... ... @@ -73,7 +73,7 @@ cd ../..
73 73 python -m api.app \
74 74 --host 0.0.0.0 \
75 75 --port 6002 \
76   - --customer customer1 \
  76 + --tenant tenant1 \
77 77 --es-host http://localhost:9200
78 78  
79 79 # 4. Test various searches
... ... @@ -118,7 +118,7 @@ python -c "from embeddings import CLIPImageEncoder; CLIPImageEncoder()"
118 118 ### Issue: Out of memory during embedding generation
119 119 **Solution**: Reduce batch size or skip embeddings initially
120 120 ```bash
121   -python ingest_customer1.py --skip-embeddings --limit 1000
  121 +python ingest_tenant1.py --skip-embeddings --limit 1000
122 122 ```
123 123  
124 124 ### Issue: Translation not working
... ... @@ -164,7 +164,7 @@ curl -X POST http://localhost:6002/search/ \
164 164  
165 165 ## What's Next?
166 166  
167   -1. **Customize Configuration**: Edit `config/schema/customer1_config.yaml`
  167 +1. **Customize Configuration**: Edit `config/schema/tenant1_config.yaml`
168 168 2. **Add More Data**: Ingest your own product data
169 169 3. **Tune Ranking**: Adjust ranking expression in config
170 170 4. **Add Rewrite Rules**: Update via API `/admin/rewrite-rules`
... ...
USER_GUIDE.md
... ... @@ -96,7 +96,7 @@ REDIS_PASSWORD=BMfv5aI31kgHWtlx
96 96 DEEPL_AUTH_KEY=c9293ab4-ad25-479b-919f-ab4e63b429ed
97 97  
98 98 # 客户配置
99   -CUSTOMER_ID=customer1
  99 +TENANT_ID=tenant1
100 100  
101 101 # API服务配置
102 102 API_HOST=0.0.0.0
... ... @@ -292,7 +292,7 @@ from search import Searcher
292 292 from config.env_config import get_es_config
293 293  
294 294 config_loader = ConfigLoader('config/schema')
295   -config = config_loader.load_customer_config('customer1')
  295 +config = config_loader.load_tenant_config('tenant1')
296 296  
297 297 es_config = get_es_config()
298 298 es_client = ESClient(hosts=[es_config['host']],
... ... @@ -326,7 +326,7 @@ for hit in result.hits:
326 326 ### 2. 批量大小调整
327 327  
328 328 ```bash
329   -# 修改批量大小(在ingest_customer1.py中)
  329 +# 修改批量大小(在ingest_tenant1.py中)
330 330 --batch-size 200 # 默认100
331 331 ```
332 332  
... ... @@ -369,4 +369,4 @@ SearchEngine/
369 369 遇到问题请查看:
370 370 - **日志**: `logs/backend.log`
371 371 - **API文档**: http://localhost:6002/docs
372   -- **配置**: `config/schema/customer1_config.yaml`
  372 +- **配置**: `config/schema/tenant1_config.yaml`
... ...
VISUAL_COMPARISON.md
... ... @@ -69,7 +69,7 @@
69 69 #### 旧版
70 70 ```
71 71 🔍 电商搜索引擎
72   -E-Commerce Search Engine - Customer1 Demo
  72 +E-Commerce Search Engine - Tenant1 Demo
73 73 ```
74 74 - 大标题 + 副标题
75 75 - 表情符号
... ...
docs/TestingPipeline_README.md
... ... @@ -193,7 +193,7 @@ python scripts/run_performance_tests.py
193 193 export ES_PASSWORD="changeme"
194 194 export API_HOST="127.0.0.1"
195 195 export API_PORT="6003"
196   - export CUSTOMER_ID="test_customer"
  196 + export TENANT_ID="test_tenant"
197 197 export TESTING_MODE="true"
198 198 ```
199 199  
... ... @@ -323,9 +323,9 @@ test_logs/
323 323 ```python
324 324 # 使用fixture提供测试数据
325 325 @pytest.fixture
326   -def sample_customer_config():
327   - return CustomerConfig(
328   - customer_id="test_customer",
  326 +def sample_tenant_config():
  327 + return TenantConfig(
  328 + tenant_id="test_tenant",
329 329 es_index_name="test_products"
330 330 )
331 331  
... ...
docs/店匠相关资料/SHOPLAZZA_INTEGRATION_GUIDE.md
... ... @@ -157,7 +157,7 @@ https://your-domain.com/oauth/callback
157 157 | `read_product` | 读取商品信息 | ✅ 必需 |
158 158 | `write_product` | 修改商品信息 | ❌ 可选 |
159 159 | `read_order` | 读取订单信息 | ✅ 必需 |
160   -| `read_customer` | 读取客户信息 | ✅ 必需 |
  160 +| `read_tenant` | 读取客户信息 | ✅ 必需 |
161 161 | `read_app_proxy` | APP 代理访问 | ✅ 必需 |
162 162 | `write_cart_transform` | 购物车转换(如需价格调整) | ❌ 可选 |
163 163  
... ... @@ -167,7 +167,7 @@ Scopes: []string{
167 167 "read_shop",
168 168 "read_product",
169 169 "read_order",
170   - "read_customer",
  170 + "read_tenant",
171 171 "read_app_proxy",
172 172 }
173 173 ```
... ... @@ -239,7 +239,7 @@ config := &OAuthConfig{
239 239 "read_shop",
240 240 "read_product",
241 241 "read_order",
242   - "read_customer",
  242 + "read_tenant",
243 243 "read_app_proxy",
244 244 },
245 245 AuthURL: "https://partners.shoplazza.com/partner/oauth/authorize",
... ... @@ -286,7 +286,7 @@ func buildAuthURL(config *OAuthConfig, shop string) string {
286 286 https://partners.shoplazza.com/partner/oauth/authorize?
287 287 client_id=m8F9PrPnxpyrlz4ONBWRoINsa5xyNT4Qd-Fh_h7o1es
288 288 &redirect_uri=https://your-domain.com/oauth/callback
289   - &scope=read_shop read_product read_order read_customer read_app_proxy
  289 + &scope=read_shop read_product read_order read_tenant read_app_proxy
290 290 &state=47167113-1.myshoplaza.com
291 291 ```
292 292  
... ... @@ -742,13 +742,13 @@ GET /openapi/2022-01/orders/count
742 742  
743 743 ```bash
744 744 # 获取客户列表
745   -GET /openapi/2022-01/customers?page=1&limit=50
  745 +GET /openapi/2022-01/tenants?page=1&limit=50
746 746  
747 747 # 获取客户详情
748   -GET /openapi/2022-01/customers/{customer_id}
  748 +GET /openapi/2022-01/tenants/{tenant_id}
749 749  
750 750 # 获取客户总数
751   -GET /openapi/2022-01/customers/count
  751 +GET /openapi/2022-01/tenants/count
752 752 ```
753 753  
754 754 ### 5.4 请求和响应格式
... ... @@ -1222,14 +1222,14 @@ public class ProductSyncService {
1222 1222  
1223 1223 #### 6.2.1 数据表设计
1224 1224  
1225   -**客户表(shoplazza_customer):**
  1225 +**客户表(shoplazza_tenant):**
1226 1226  
1227 1227 ```sql
1228   -CREATE TABLE `shoplazza_customer` (
  1228 +CREATE TABLE `shoplazza_tenant` (
1229 1229 `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
1230 1230 `tenant_id` BIGINT NOT NULL COMMENT '租户ID',
1231 1231 `store_id` VARCHAR(64) NOT NULL COMMENT '店铺ID',
1232   - `customer_id` VARCHAR(64) NOT NULL COMMENT '店匠客户ID',
  1232 + `tenant_id` VARCHAR(64) NOT NULL COMMENT '店匠客户ID',
1233 1233 `email` VARCHAR(255) DEFAULT NULL COMMENT '邮箱',
1234 1234 `phone` VARCHAR(64) DEFAULT NULL COMMENT '电话',
1235 1235 `first_name` VARCHAR(128) DEFAULT NULL COMMENT '名',
... ... @@ -1241,20 +1241,20 @@ CREATE TABLE `shoplazza_customer` (
1241 1241 `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
1242 1242 `deleted` BIT(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
1243 1243 PRIMARY KEY (`id`),
1244   - UNIQUE KEY `uk_store_customer` (`store_id`, `customer_id`),
  1244 + UNIQUE KEY `uk_store_tenant` (`store_id`, `tenant_id`),
1245 1245 KEY `idx_tenant_id` (`tenant_id`),
1246 1246 KEY `idx_email` (`email`)
1247 1247 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='店匠客户表';
1248 1248 ```
1249 1249  
1250   -**客户地址表(shoplazza_customer_address):**
  1250 +**客户地址表(shoplazza_tenant_address):**
1251 1251  
1252 1252 ```sql
1253   -CREATE TABLE `shoplazza_customer_address` (
  1253 +CREATE TABLE `shoplazza_tenant_address` (
1254 1254 `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
1255 1255 `tenant_id` BIGINT NOT NULL COMMENT '租户ID',
1256 1256 `store_id` VARCHAR(64) NOT NULL COMMENT '店铺ID',
1257   - `customer_id` VARCHAR(64) NOT NULL COMMENT '店匠客户ID',
  1257 + `tenant_id` VARCHAR(64) NOT NULL COMMENT '店匠客户ID',
1258 1258 `address_id` VARCHAR(64) NOT NULL COMMENT '店匠地址ID',
1259 1259 `first_name` VARCHAR(128) DEFAULT NULL COMMENT '名',
1260 1260 `last_name` VARCHAR(128) DEFAULT NULL COMMENT '姓',
... ... @@ -1272,7 +1272,7 @@ CREATE TABLE `shoplazza_customer_address` (
1272 1272 PRIMARY KEY (`id`),
1273 1273 UNIQUE KEY `uk_store_address` (`store_id`, `address_id`),
1274 1274 KEY `idx_tenant_id` (`tenant_id`),
1275   - KEY `idx_customer_id` (`customer_id`)
  1275 + KEY `idx_tenant_id` (`tenant_id`)
1276 1276 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='店匠客户地址表';
1277 1277 ```
1278 1278  
... ... @@ -1280,7 +1280,7 @@ CREATE TABLE `shoplazza_customer_address` (
1280 1280  
1281 1281 ```bash
1282 1282 curl --request GET \
1283   - --url 'https://47167113-1.myshoplaza.com/openapi/2022-01/customers?page=1&limit=50' \
  1283 + --url 'https://47167113-1.myshoplaza.com/openapi/2022-01/tenants?page=1&limit=50' \
1284 1284 --header 'access-token: V2WDYgkTvrN68QCESZ9eHb3EjpR6EBrPyAKe-m_JwYY' \
1285 1285 --header 'accept: application/json'
1286 1286 ```
... ... @@ -1298,7 +1298,7 @@ CREATE TABLE `shoplazza_order` (
1298 1298 `store_id` VARCHAR(64) NOT NULL COMMENT '店铺ID',
1299 1299 `order_id` VARCHAR(64) NOT NULL COMMENT '店匠订单ID',
1300 1300 `order_number` VARCHAR(128) NOT NULL COMMENT '订单号',
1301   - `customer_id` VARCHAR(64) DEFAULT NULL COMMENT '客户ID',
  1301 + `tenant_id` VARCHAR(64) DEFAULT NULL COMMENT '客户ID',
1302 1302 `email` VARCHAR(255) DEFAULT NULL COMMENT '客户邮箱',
1303 1303 `total_price` DECIMAL(12,2) NOT NULL COMMENT '订单总价',
1304 1304 `subtotal_price` DECIMAL(12,2) DEFAULT NULL COMMENT '小计',
... ... @@ -1314,7 +1314,7 @@ CREATE TABLE `shoplazza_order` (
1314 1314 PRIMARY KEY (`id`),
1315 1315 UNIQUE KEY `uk_store_order` (`store_id`, `order_id`),
1316 1316 KEY `idx_tenant_id` (`tenant_id`),
1317   - KEY `idx_customer_id` (`customer_id`),
  1317 + KEY `idx_tenant_id` (`tenant_id`),
1318 1318 KEY `idx_order_number` (`order_number`)
1319 1319 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='店匠订单表';
1320 1320 ```
... ... @@ -1365,7 +1365,7 @@ public class DataSyncService {
1365 1365 productSyncService.syncProducts(shopConfigId);
1366 1366  
1367 1367 // 2. 同步客户
1368   - customerSyncService.syncCustomers(shopConfigId);
  1368 + tenantSyncService.syncTenants(shopConfigId);
1369 1369  
1370 1370 // 3. 同步订单
1371 1371 orderSyncService.syncOrders(shopConfigId);
... ... @@ -1420,12 +1420,12 @@ public class ScheduledSyncTask {
1420 1420 * 每天同步一次客户和订单数据
1421 1421 */
1422 1422 @Scheduled(cron = "0 0 3 * * ?")
1423   - public void syncCustomersAndOrdersDaily() {
  1423 + public void syncTenantsAndOrdersDaily() {
1424 1424 List<ShopConfig> activeShops = shopConfigMapper.selectActiveShops();
1425 1425  
1426 1426 for (ShopConfig shop : activeShops) {
1427 1427 try {
1428   - customerSyncService.syncCustomers(shop.getId());
  1428 + tenantSyncService.syncTenants(shop.getId());
1429 1429 orderSyncService.syncOrders(shop.getId());
1430 1430 } catch (Exception e) {
1431 1431 log.error("Scheduled sync failed for shop: {}", shop.getStoreName(), e);
... ... @@ -1453,8 +1453,8 @@ public class RobustSyncService {
1453 1453 case "products":
1454 1454 productSyncService.syncProducts(shopConfigId);
1455 1455 break;
1456   - case "customers":
1457   - customerSyncService.syncCustomers(shopConfigId);
  1456 + case "tenants":
  1457 + tenantSyncService.syncTenants(shopConfigId);
1458 1458 break;
1459 1459 case "orders":
1460 1460 orderSyncService.syncOrders(shopConfigId);
... ... @@ -1512,9 +1512,9 @@ Webhook 是店匠平台的事件通知机制,当店铺发生特定事件(如
1512 1512  
1513 1513 | Topic | 说明 | 触发时机 |
1514 1514 |-------|------|----------|
1515   -| `customers/create` | 客户创建 | 新客户注册时 |
1516   -| `customers/update` | 客户更新 | 客户信息更新时 |
1517   -| `customers/delete` | 客户删除 | 客户被删除时 |
  1515 +| `tenants/create` | 客户创建 | 新客户注册时 |
  1516 +| `tenants/update` | 客户更新 | 客户信息更新时 |
  1517 +| `tenants/delete` | 客户删除 | 客户被删除时 |
1518 1518  
1519 1519 ### 7.3 注册 Webhook
1520 1520  
... ... @@ -1561,8 +1561,8 @@ public class WebhookService {
1561 1561 "orders/create",
1562 1562 "orders/updated",
1563 1563 "orders/paid",
1564   - "customers/create",
1565   - "customers/update"
  1564 + "tenants/create",
  1565 + "tenants/update"
1566 1566 );
1567 1567  
1568 1568 /**
... ... @@ -1733,12 +1733,12 @@ public class WebhookService {
1733 1733 case "orders/cancelled":
1734 1734 handleOrderCancel(storeId, payload);
1735 1735 break;
1736   - case "customers/create":
1737   - case "customers/update":
1738   - handleCustomerUpdate(storeId, payload);
  1736 + case "tenants/create":
  1737 + case "tenants/update":
  1738 + handleTenantUpdate(storeId, payload);
1739 1739 break;
1740   - case "customers/delete":
1741   - handleCustomerDelete(storeId, payload);
  1740 + case "tenants/delete":
  1741 + handleTenantDelete(storeId, payload);
1742 1742 break;
1743 1743 default:
1744 1744 log.warn("Unknown webhook topic: {}", topic);
... ... @@ -2279,7 +2279,7 @@ public class SearchService {
2279 2279 String url = searchServiceUrl + "/search/";
2280 2280  
2281 2281 // 添加租户隔离参数
2282   - request.setCustomer("tenant_" + tenantId);
  2282 + request.setTenant("tenant_" + tenantId);
2283 2283  
2284 2284 ResponseEntity<SearchResponse> response = restTemplate.postForEntity(
2285 2285 url,
... ... @@ -2309,8 +2309,8 @@ public class SearchService {
2309 2309 # Python 搜索服务
2310 2310 @app.post("/search/")
2311 2311 async def search_products(request: SearchRequest):
2312   - # 根据 customer 参数确定租户 ID
2313   - tenant_id = extract_tenant_id(request.customer)
  2312 + # 根据 tenant 参数确定租户 ID
  2313 + tenant_id = extract_tenant_id(request.tenant)
2314 2314  
2315 2315 # 使用租户专属索引
2316 2316 index_name = f"shoplazza_products_{tenant_id}"
... ... @@ -2337,7 +2337,7 @@ CREATE TABLE `shoplazza_search_log` (
2337 2337 `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
2338 2338 `tenant_id` BIGINT NOT NULL COMMENT '租户ID',
2339 2339 `store_id` VARCHAR(64) NOT NULL COMMENT '店铺ID',
2340   - `customer_id` VARCHAR(64) DEFAULT NULL COMMENT '客户ID',
  2340 + `tenant_id` VARCHAR(64) DEFAULT NULL COMMENT '客户ID',
2341 2341 `session_id` VARCHAR(128) DEFAULT NULL COMMENT '会话ID',
2342 2342 `query` VARCHAR(512) NOT NULL COMMENT '搜索关键词',
2343 2343 `results_count` INT DEFAULT 0 COMMENT '结果数量',
... ... @@ -2377,7 +2377,7 @@ public class SearchLogService {
2377 2377 SearchLog log = new SearchLog();
2378 2378 log.setTenantId(shop.getTenantId());
2379 2379 log.setStoreId(shop.getStoreId());
2380   - log.setCustomerId(request.getCustomerId());
  2380 + log.setTenantId(request.getTenantId());
2381 2381 log.setSessionId(request.getSessionId());
2382 2382 log.setQuery(request.getQuery());
2383 2383 log.setResultsCount(response.getTotal());
... ... @@ -2647,7 +2647,7 @@ window.AI_SEARCH_CONFIG = {
2647 2647 size: 24,
2648 2648 filters: currentFilters,
2649 2649 facets: ['product_type', 'vendor', 'tags'],
2650   - customer: `tenant_${config.storeId}`
  2650 + tenant: `tenant_${config.storeId}`
2651 2651 })
2652 2652 });
2653 2653  
... ... @@ -3023,8 +3023,8 @@ server {
3023 3023 | 订单列表 | `/openapi/2022-01/orders` | GET | 获取订单列表 |
3024 3024 | 订单详情 | `/openapi/2022-01/orders/{id}` | GET | 获取单个订单 |
3025 3025 | **客户** |
3026   -| 客户列表 | `/openapi/2022-01/customers` | GET | 获取客户列表 |
3027   -| 客户详情 | `/openapi/2022-01/customers/{id}` | GET | 获取单个客户 |
  3026 +| 客户列表 | `/openapi/2022-01/tenants` | GET | 获取客户列表 |
  3027 +| 客户详情 | `/openapi/2022-01/tenants/{id}` | GET | 获取单个客户 |
3028 3028 | **Webhook** |
3029 3029 | 注册 Webhook | `/openapi/2022-01/webhooks` | POST | 注册事件通知 |
3030 3030 | Webhook 列表 | `/openapi/2022-01/webhooks` | GET | 获取已注册列表 |
... ... @@ -3039,7 +3039,7 @@ curl -X POST http://your-domain:6002/search/ \
3039 3039 -H "Content-Type: application/json" \
3040 3040 -d '{
3041 3041 "query": "bluetooth headphone",
3042   - "customer": "tenant_1",
  3042 + "tenant": "tenant_1",
3043 3043 "size": 20,
3044 3044 "from": 0,
3045 3045 "filters": {
... ... @@ -3056,7 +3056,7 @@ curl -X POST http://your-domain:6002/search/image \
3056 3056 -H "Content-Type: application/json" \
3057 3057 -d '{
3058 3058 "image_url": "https://example.com/image.jpg",
3059   - "customer": "tenant_1",
  3059 + "tenant": "tenant_1",
3060 3060 "size": 20
3061 3061 }'
3062 3062 ```
... ... @@ -3071,8 +3071,8 @@ curl -X POST http://your-domain:6002/search/image \
3071 3071 - `shoplazza_product_spu` - 商品 SPU 表
3072 3072 - `shoplazza_product_sku` - 商品 SKU 表
3073 3073 - `shoplazza_product_image` - 商品图片表
3074   -- `shoplazza_customer` - 客户表
3075   -- `shoplazza_customer_address` - 客户地址表
  3074 +- `shoplazza_tenant` - 客户表
  3075 +- `shoplazza_tenant_address` - 客户地址表
3076 3076 - `shoplazza_order` - 订单表
3077 3077 - `shoplazza_order_item` - 订单明细表
3078 3078 - `shoplazza_search_log` - 搜索日志表
... ... @@ -3092,7 +3092,7 @@ shoplazza:
3092 3092 - read_shop
3093 3093 - read_product
3094 3094 - read_order
3095   - - read_customer
  3095 + - read_tenant
3096 3096 - read_app_proxy
3097 3097  
3098 3098 # Webhook 配置
... ... @@ -3103,7 +3103,7 @@ shoplazza:
3103 3103 - products/update
3104 3104 - products/delete
3105 3105 - orders/create
3106   - - customers/create
  3106 + - tenants/create
3107 3107  
3108 3108 # 搜索服务配置
3109 3109 search:
... ... @@ -3130,7 +3130,7 @@ sync:
3130 3130 schedule:
3131 3131 products: "0 0 */1 * * ?" # 每小时
3132 3132 orders: "0 0 3 * * ?" # 每天凌晨3点
3133   - customers: "0 0 4 * * ?" # 每天凌晨4点
  3133 + tenants: "0 0 4 * * ?" # 每天凌晨4点
3134 3134 ```
3135 3135  
3136 3136 ### 12.4 故障排查
... ...
docs/店匠相关资料/记录tenant和token-获取商品信息.md
... ... @@ -127,7 +127,7 @@ public void handleOAuthCallback(TokenResponse tokenResponse) {
127 127 1. **拉取数据** - 调用店匠 Admin API
128 128 - 拉取商品:`GET /openapi/2022-01/products`
129 129 - 拉取订单:`GET /openapi/2022-01/orders`
130   - - 拉取客户:`GET /openapi/2022-01/customers`
  130 + - 拉取客户:`GET /openapi/2022-01/tenants`
131 131  
132 132 2. **注册 Webhook** - 让店匠主动推送数据变更
133 133 - 注册:`POST /openapi/2022-01/webhooks`(需要 Token)
... ... @@ -255,12 +255,12 @@ public void syncProducts(Long shopConfigId) {
255 255  
256 256 **实现逻辑:**
257 257 ```java
258   -public void syncCustomers(Long shopConfigId) {
  258 +public void syncTenants(Long shopConfigId) {
259 259 // 与 syncProducts 类似,遍历所有分页
260   - String url = "https://{shop}/openapi/2022-01/customers?page={page}&limit=50";
  260 + String url = "https://{shop}/openapi/2022-01/tenants?page={page}&limit=50";
261 261  
262 262 // 循环拉取所有页
263   - // 保存到 shoplazza_customer 和 shoplazza_customer_address 表
  263 + // 保存到 shoplazza_tenant 和 shoplazza_tenant_address 表
264 264 }
265 265 ```
266 266  
... ... @@ -342,7 +342,7 @@ public class WebhookService {
342 342  
343 343 private static final List<String> WEBHOOK_TOPICS = Arrays.asList(
344 344 "products/create", "products/update", "products/delete",
345   - "orders/create", "orders/updated", "customers/create"
  345 + "orders/create", "orders/updated", "tenants/create"
346 346 );
347 347  
348 348 public void registerWebhooks(Long shopConfigId) {
... ...
frontend/unified.html
... ... @@ -54,7 +54,7 @@
54 54 <div class="tenant-selector">
55 55 <label for="tenantSelect">选择租户:</label>
56 56 <select id="tenantSelect" onchange="switchTenant()">
57   - <option value="customer1">Customer1 (旧配置)</option>
  57 + <option value="tenant1">Tenant1 (旧配置)</option>
58 58 <option value="base:1" selected>Base - Tenant 1 (店匠通用)</option>
59 59 <option value="base:2">Base - Tenant 2 (店匠通用)</option>
60 60 </select>
... ...
scripts/start_test_environment.sh
... ... @@ -61,7 +61,7 @@ export ES_PASSWORD=&quot;changeme&quot;
61 61 # API配置
62 62 export API_HOST="127.0.0.1"
63 63 export API_PORT="6003" # 使用不同的端口避免冲突
64   -export CUSTOMER_ID="test_customer"
  64 +export TENANT_ID="test_tenant"
65 65  
66 66 # 测试配置
67 67 export TEST_TIMEOUT=60
... ... @@ -70,7 +70,7 @@ export TEST_RETRY_COUNT=3
70 70 echo -e "${BLUE}环境配置:${NC}"
71 71 echo " ES_HOST: $ES_HOST"
72 72 echo " API_HOST: $API_HOST:$API_PORT"
73   -echo " CUSTOMER_ID: $CUSTOMER_ID"
  73 +echo " TENANT_ID: $TENANT_ID"
74 74 echo " LOG_LEVEL: $LOG_LEVEL"
75 75 echo " TESTING_MODE: $TESTING_MODE"
76 76  
... ... @@ -184,7 +184,7 @@ cd &quot;$PROJECT_ROOT&quot;
184 184 python -m api.app \
185 185 --host $API_HOST \
186 186 --port $API_PORT \
187   - --customer $CUSTOMER_ID \
  187 + --tenant $TENANT_ID \
188 188 --es-host $ES_HOST \
189 189 > "$API_LOG_FILE" 2>&1 &
190 190  
... ... @@ -240,7 +240,7 @@ echo -e &quot;${GREEN}========================================${NC}&quot;
240 240 echo -e "${BLUE}服务信息:${NC}"
241 241 echo " Elasticsearch: $ES_HOST"
242 242 echo " API服务: http://$API_HOST:$API_PORT"
243   -echo " 测试客户: $CUSTOMER_ID"
  243 +echo " 测试客户: $TENANT_ID"
244 244 echo -e "${BLUE}进程信息:${NC}"
245 245 echo " API PID: $API_PID"
246 246 echo " PID文件: $PID_FILE"
... ... @@ -264,7 +264,7 @@ export ES_USERNAME=&quot;$ES_USERNAME&quot;
264 264 export ES_PASSWORD="$ES_PASSWORD"
265 265 export API_HOST="$API_HOST"
266 266 export API_PORT="$API_PORT"
267   -export CUSTOMER_ID="$CUSTOMER_ID"
  267 +export TENANT_ID="$TENANT_ID"
268 268 export TESTING_MODE="$TESTING_MODE"
269 269 export LOG_LEVEL="$LOG_LEVEL"
270 270 export PYTHONPATH="$PROJECT_ROOT:\$PYTHONPATH"
... ...
支持多语言查询.md
... ... @@ -36,7 +36,7 @@ index 8df15b3..f3fcaa3 100644
36 36  
37 37 @dataclass
38 38 class RankingConfig:
39   -@@ -66,8 +69,6 @@ class CustomerConfig:
  39 +@@ -66,8 +69,6 @@ class TenantConfig:
40 40  
41 41 # Database settings
42 42 mysql_config: Dict[str, Any]
... ... @@ -45,7 +45,7 @@ index 8df15b3..f3fcaa3 100644
45 45  
46 46 # Field definitions
47 47 fields: List[FieldConfig]
48   -@@ -86,6 +87,10 @@ class CustomerConfig:
  48 +@@ -86,6 +87,10 @@ class TenantConfig:
49 49  
50 50 # ES index settings
51 51 es_index_name: str
... ... @@ -74,7 +74,7 @@ index 8df15b3..f3fcaa3 100644
74 74 + language_field_mapping=language_field_mapping
75 75 )
76 76  
77   - def validate_config(self, config: CustomerConfig) -> List[str]:
  77 + def validate_config(self, config: TenantConfig) -> List[str]:
78 78 @@ -360,11 +369,16 @@ class ConfigLoader:
79 79  
80 80 def _index_to_dict(self, index: IndexConfig) -> Dict[str, Any]:
... ... @@ -96,10 +96,10 @@ index 8df15b3..f3fcaa3 100644
96 96 +
97 97 + return result
98 98 \ No newline at end of file
99   -diff --git a/config/schema/customer1_config.yaml b/config/schema/customer1_config.yaml
  99 +diff --git a/config/schema/tenant1_config.yaml b/config/schema/tenant1_config.yaml
100 100 index bfe2e53..84e9ba1 100644
101   ---- a/config/schema/customer1_config.yaml
102   -+++ b/config/schema/customer1_config.yaml
  101 +--- a/config/schema/tenant1_config.yaml
  102 ++++ b/config/schema/tenant1_config.yaml
103 103 @@ -177,6 +177,15 @@ indexes:
104 104 analyzer: "chinese_ecommerce"
105 105 boost: 1.0
... ...
设计文档.md
... ... @@ -70,7 +70,7 @@
70 70  
71 71 ### 2.1 搴旂敤缁撴瀯閰嶇疆锛堝瓧娈靛畾涔夛級
72 72  
73   -**閰嶇疆鏂囦欢浣嶇疆**锛歚config/schema/{customer_id}_config.yaml`
  73 +**閰嶇疆鏂囦欢浣嶇疆**锛歚config/schema/{tenant_id}_config.yaml`
74 74  
75 75 **閰嶇疆鍐呭**锛氬畾涔変簡 ES 鐨勮緭鍏ユ暟鎹湁鍝簺瀛楁銆佸叧鑱 MySQL 鐨勫摢浜涘瓧娈点
76 76  
... ... @@ -228,7 +228,7 @@ indexes:
228 228 - `shoplazza_product_spu` - SPU绾у埆鍟嗗搧鏁版嵁
229 229 - `shoplazza_product_sku` - SKU绾у埆鍟嗗搧鏁版嵁
230 230  
231   -**鍏朵粬瀹㈡埛琛**锛坈ustomer1绛夛級锛
  231 +**鍏朵粬瀹㈡埛琛**锛坱enant1绛夛級锛
232 232 - 浣跨敤鍚勮嚜鐨勬暟鎹簮琛ㄥ拰鎵╁睍琛
233 233  
234 234 ### 3.2 鏁版嵁瀵煎叆鏂瑰紡
... ... @@ -585,7 +585,7 @@ API杩斿洖鏍煎紡涓嶅寘鍚獷S鍐呴儴瀛楁锛坄_id`, `_score`, `_source`锛夛紝浣跨敤
585 585  
586 586 **Base閰嶇疆**锛堝簵鍖犻氱敤锛夛細`config/schema/base/config.yaml`
587 587  
588   -**鍏朵粬瀹㈡埛閰嶇疆**锛歚config/schema/customer1/config.yaml`
  588 +**鍏朵粬瀹㈡埛閰嶇疆**锛歚config/schema/tenant1/config.yaml`
589 589  
590 590 ---
591 591  
... ...