Commit ae5a294d3f93b6542de1831d70c239f2213e1145
1 parent
37e994bb
命名修改、代码清理
Showing
27 changed files
with
215 additions
and
215 deletions
Show diff stats
.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
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
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="changeme" |
| 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 "$PROJECT_ROOT" |
| 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 "${GREEN}========================================${NC}" |
| 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="$ES_USERNAME" |
| 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 | ... | ... |