Commit 11237cf2218f281a55e60066a28c1f035f33ef7f
1 parent
3c1f8031
搜索API对接指南.md
Showing
1 changed file
with
526 additions
and
512 deletions
Show diff stats
docs/搜索API对接指南.md
| ... | ... | @@ -5,16 +5,61 @@ |
| 5 | 5 | ## 目录 |
| 6 | 6 | |
| 7 | 7 | 1. [快速开始](#快速开始) |
| 8 | + - 1.1 [基础信息](#11-基础信息) | |
| 9 | + - 1.2 [最简单的搜索请求](#12-最简单的搜索请求) | |
| 10 | + - 1.3 [带过滤与分页的搜索](#13-带过滤与分页的搜索) | |
| 11 | + - 1.4 [开启分面的搜索](#14-开启分面的搜索) | |
| 12 | + | |
| 8 | 13 | 2. [接口概览](#接口概览) |
| 14 | + | |
| 9 | 15 | 3. [搜索接口](#搜索接口) |
| 16 | + - 3.1 [接口信息](#31-接口信息) | |
| 17 | + - 3.2 [请求参数](#32-请求参数) | |
| 18 | + - 3.3 [过滤器详解](#33-过滤器详解) | |
| 19 | + - 3.4 [分面配置](#34-分面配置) | |
| 20 | + - 3.5 [SKU筛选维度](#35-sku筛选维度) | |
| 21 | + - 3.6 [布尔表达式语法](#36-布尔表达式语法) | |
| 22 | + - 3.7 [搜索建议接口](#37-搜索建议接口) | |
| 23 | + - 3.8 [即时搜索接口](#38-即时搜索接口) | |
| 24 | + - 3.9 [获取单个文档](#39-获取单个文档) | |
| 25 | + | |
| 10 | 26 | 4. [响应格式说明](#响应格式说明) |
| 11 | -5. [常见场景示例](#常见场景示例) | |
| 27 | + - 4.1 [标准响应结构](#41-标准响应结构) | |
| 28 | + - 4.2 [响应字段说明](#42-响应字段说明) | |
| 29 | + - 4.3 [SpuResult字段说明](#43-spuresult字段说明) | |
| 30 | + - 4.4 [SkuResult字段说明](#44-skuresult字段说明) | |
| 31 | + - 4.5 [多语言字段说明](#45-多语言字段说明) | |
| 32 | + | |
| 33 | +5. [索引接口](#索引接口) | |
| 34 | + - 5.1 [全量索引接口](#51-全量索引接口) | |
| 35 | + - 5.2 [SPU索引接口](#52-spu索引接口) | |
| 36 | + - 5.3 [索引健康检查接口](#53-索引健康检查接口) | |
| 37 | + | |
| 38 | +6. [管理接口](#管理接口) | |
| 39 | + - 6.1 [健康检查](#61-健康检查) | |
| 40 | + - 6.2 [获取配置](#62-获取配置) | |
| 41 | + - 6.3 [索引统计](#63-索引统计) | |
| 42 | + | |
| 43 | +7. [常见场景示例](#常见场景示例) | |
| 44 | + - 7.1 [基础搜索与排序](#71-基础搜索与排序) | |
| 45 | + - 7.2 [过滤搜索](#72-过滤搜索) | |
| 46 | + - 7.3 [分面搜索](#73-分面搜索) | |
| 47 | + - 7.4 [规格过滤与分面](#74-规格过滤与分面) | |
| 48 | + - 7.5 [SKU筛选](#75-sku筛选) | |
| 49 | + - 7.6 [布尔表达式搜索](#76-布尔表达式搜索) | |
| 50 | + - 7.7 [分页查询](#77-分页查询) | |
| 51 | + | |
| 52 | +8. [数据模型](#数据模型) | |
| 53 | + - 8.1 [商品字段定义](#81-商品字段定义) | |
| 54 | + - 8.2 [字段类型速查](#82-字段类型速查) | |
| 55 | + - 8.3 [常用字段列表](#83-常用字段列表) | |
| 56 | + - 8.4 [支持的分析器](#84-支持的分析器) | |
| 12 | 57 | |
| 13 | 58 | --- |
| 14 | 59 | |
| 15 | 60 | ## 快速开始 |
| 16 | 61 | |
| 17 | -### 基础信息 | |
| 62 | +### 1.1 基础信息 | |
| 18 | 63 | |
| 19 | 64 | - **Base URL**: `http://your-domain:6002` 或 `http://120.76.41.98:6002` |
| 20 | 65 | - **协议**: HTTP/HTTPS |
| ... | ... | @@ -22,7 +67,9 @@ |
| 22 | 67 | - **字符编码**: UTF-8 |
| 23 | 68 | - **请求方法**: POST(搜索接口) |
| 24 | 69 | |
| 25 | -### 最简单的搜索请求 | |
| 70 | +**重要提示**: `tenant_id` 通过 HTTP Header `X-Tenant-ID` 传递,不在请求体中。 | |
| 71 | + | |
| 72 | +### 1.2 最简单的搜索请求 | |
| 26 | 73 | |
| 27 | 74 | ```bash |
| 28 | 75 | curl -X POST "http://120.76.41.98:6002/search/" \ |
| ... | ... | @@ -31,7 +78,7 @@ curl -X POST "http://120.76.41.98:6002/search/" \ |
| 31 | 78 | -d '{"query": "芭比娃娃"}' |
| 32 | 79 | ``` |
| 33 | 80 | |
| 34 | -### curl示例:带过滤与分页 | |
| 81 | +### 1.3 带过滤与分页的搜索 | |
| 35 | 82 | |
| 36 | 83 | ```bash |
| 37 | 84 | curl -X POST "http://120.76.41.98:6002/search/" \ |
| ... | ... | @@ -41,21 +88,21 @@ curl -X POST "http://120.76.41.98:6002/search/" \ |
| 41 | 88 | "query": "芭比娃娃", |
| 42 | 89 | "size": 5, |
| 43 | 90 | "from": 10, |
| 44 | - "range_filters": { | |
| 45 | - "min_price": { | |
| 46 | - "gte": 50, | |
| 47 | - "lte": 200 | |
| 91 | + "range_filters": { | |
| 92 | + "min_price": { | |
| 93 | + "gte": 50, | |
| 94 | + "lte": 200 | |
| 95 | + }, | |
| 96 | + "create_time": { | |
| 97 | + "gte": "2020-01-01T00:00:00Z" | |
| 98 | + } | |
| 48 | 99 | }, |
| 49 | - "create_time": { | |
| 50 | - "gte": "2020-01-01T00:00:00Z" | |
| 51 | - } | |
| 52 | - }, | |
| 53 | 100 | "sort_by": "price", |
| 54 | 101 | "sort_order": "asc" |
| 55 | 102 | }' |
| 56 | 103 | ``` |
| 57 | 104 | |
| 58 | -### curl示例:开启分面 | |
| 105 | +### 1.4 开启分面的搜索 | |
| 59 | 106 | |
| 60 | 107 | ```bash |
| 61 | 108 | curl -X POST "http://120.76.41.98:6002/search/" \ |
| ... | ... | @@ -79,199 +126,26 @@ curl -X POST "http://120.76.41.98:6002/search/" \ |
| 79 | 126 | | 接口 | HTTP Method | Endpoint | 说明 | |
| 80 | 127 | |------|------|------|------| |
| 81 | 128 | | 搜索 | POST | `/search/` | 执行搜索查询 | |
| 129 | +| 搜索建议 | GET | `/search/suggestions` | 搜索建议(框架,暂未实现) ⚠️ TODO | | |
| 130 | +| 即时搜索 | GET | `/search/instant` | 边输入边搜索(框架) ⚠️ TODO | | |
| 131 | +| 获取文档 | GET | `/search/{doc_id}` | 获取单个文档 | | |
| 82 | 132 | | 全量索引 | POST | `/indexer/bulk` | 全量索引接口 | |
| 83 | 133 | | SPU索引 | POST | `/indexer/spus` | 获取SPU文档(支持单个或批量) | |
| 84 | 134 | | 索引健康检查 | GET | `/indexer/health` | 检查索引服务状态 | |
| 85 | -| 搜索建议(框架,暂未实现) | GET | `/search/suggestions` | 搜索建议 | | |
| 86 | -| 获取文档 | GET | `/search/{doc_id}` | 获取单个文档 | | |
| 87 | 135 | | 健康检查 | GET | `/admin/health` | 服务健康检查 | |
| 88 | - | |
| 89 | ---- | |
| 90 | - | |
| 91 | -## 索引接口 | |
| 92 | - | |
| 93 | -### 全量索引接口 | |
| 94 | - | |
| 95 | -- **端点**: `POST /indexer/bulk` | |
| 96 | -- **描述**: 将指定租户的所有SPU数据导入到ES索引 | |
| 97 | - | |
| 98 | -#### 请求参数 | |
| 99 | - | |
| 100 | -```json | |
| 101 | -{ | |
| 102 | - "tenant_id": "162", | |
| 103 | - "recreate_index": false, | |
| 104 | - "batch_size": 500 | |
| 105 | -} | |
| 106 | -``` | |
| 107 | - | |
| 108 | -| 参数 | 类型 | 必填 | 默认值 | 说明 | | |
| 109 | -|------|------|------|--------|------| | |
| 110 | -| `tenant_id` | string | Y | - | 租户ID | | |
| 111 | -| `recreate_index` | boolean | N | false | 是否重建索引(删除旧索引后创建新索引) | | |
| 112 | -| `batch_size` | integer | N | 500 | 批量导入大小 | | |
| 113 | - | |
| 114 | -#### 响应格式 | |
| 115 | - | |
| 116 | -**成功响应(200 OK)**: | |
| 117 | -```json | |
| 118 | -{ | |
| 119 | - "success": true, | |
| 120 | - "total": 1000, | |
| 121 | - "indexed": 1000, | |
| 122 | - "failed": 0, | |
| 123 | - "elapsed_time": 12.34, | |
| 124 | - "index_name": "search_products", | |
| 125 | - "tenant_id": "162" | |
| 126 | -} | |
| 127 | -``` | |
| 128 | - | |
| 129 | -**错误响应**: | |
| 130 | -- `400 Bad Request`: 参数错误 | |
| 131 | -- `503 Service Unavailable`: 服务未初始化 | |
| 132 | - | |
| 133 | -#### 请求示例 | |
| 134 | - | |
| 135 | -**首次索引(重建索引)**: | |
| 136 | -```bash | |
| 137 | -curl -X POST "http://localhost:6002/indexer/bulk" \ | |
| 138 | - -H "Content-Type: application/json" \ | |
| 139 | - -d '{ | |
| 140 | - "tenant_id": "162", | |
| 141 | - "recreate_index": true, | |
| 142 | - "batch_size": 500 | |
| 143 | - }' | |
| 144 | -``` | |
| 145 | - | |
| 146 | -**查看日志**: | |
| 147 | -```bash | |
| 148 | -# 查看API日志(包含索引操作日志) | |
| 149 | -tail -f logs/api.log | |
| 150 | - | |
| 151 | -# 或者查看所有日志文件 | |
| 152 | -tail -f logs/*.log | |
| 153 | -``` | |
| 154 | - | |
| 155 | -**增量更新(不重建索引)**: | |
| 156 | -```bash | |
| 157 | -curl -X POST "http://localhost:6002/indexer/bulk" \ | |
| 158 | - -H "Content-Type: application/json" \ | |
| 159 | - -d '{ | |
| 160 | - "tenant_id": "162", | |
| 161 | - "recreate_index": false, | |
| 162 | - "batch_size": 500 | |
| 163 | - }' | |
| 164 | -``` | |
| 165 | - | |
| 166 | ---- | |
| 167 | - | |
| 168 | -### SPU索引接口 | |
| 169 | - | |
| 170 | -- **端点**: `POST /indexer/spus` | |
| 171 | -- **描述**: 获取SPU的ES文档数据(支持单个或批量) | |
| 172 | - | |
| 173 | -#### 请求参数 | |
| 174 | - | |
| 175 | -```json | |
| 176 | -{ | |
| 177 | - "tenant_id": "162", | |
| 178 | - "spu_ids": ["123", "456", "789"] | |
| 179 | -} | |
| 180 | -``` | |
| 181 | - | |
| 182 | -| 参数 | 类型 | 必填 | 说明 | | |
| 183 | -|------|------|------|------| | |
| 184 | -| `tenant_id` | string | Y | 租户ID | | |
| 185 | -| `spu_ids` | array[string] | Y | SPU ID列表(1-100个) | | |
| 186 | - | |
| 187 | -#### 响应格式 | |
| 188 | - | |
| 189 | -```json | |
| 190 | -{ | |
| 191 | - "success": [ | |
| 192 | - { | |
| 193 | - "spu_id": "123", | |
| 194 | - "document": { | |
| 195 | - "tenant_id": "162", | |
| 196 | - "spu_id": "123", | |
| 197 | - "title_zh": "商品标题", | |
| 198 | - ... | |
| 199 | - } | |
| 200 | - }, | |
| 201 | - { | |
| 202 | - "spu_id": "456", | |
| 203 | - "document": {...} | |
| 204 | - } | |
| 205 | - ], | |
| 206 | - "failed": [ | |
| 207 | - { | |
| 208 | - "spu_id": "789", | |
| 209 | - "error": "SPU not found or deleted" | |
| 210 | - } | |
| 211 | - ], | |
| 212 | - "total": 3, | |
| 213 | - "success_count": 2, | |
| 214 | - "failed_count": 1 | |
| 215 | -} | |
| 216 | -``` | |
| 217 | - | |
| 218 | -#### 请求示例 | |
| 219 | - | |
| 220 | -**单个SPU**: | |
| 221 | -```bash | |
| 222 | -curl -X POST "http://localhost:6002/indexer/spus" \ | |
| 223 | - -H "Content-Type: application/json" \ | |
| 224 | - -d '{ | |
| 225 | - "tenant_id": "162", | |
| 226 | - "spu_ids": ["123"] | |
| 227 | - }' | |
| 228 | -``` | |
| 229 | - | |
| 230 | -**批量SPU**: | |
| 231 | -```bash | |
| 232 | -curl -X POST "http://localhost:6002/indexer/spus" \ | |
| 233 | - -H "Content-Type: application/json" \ | |
| 234 | - -d '{ | |
| 235 | - "tenant_id": "162", | |
| 236 | - "spu_ids": ["123", "456", "789"] | |
| 237 | - }' | |
| 238 | -``` | |
| 239 | - | |
| 240 | ---- | |
| 241 | - | |
| 242 | -### 索引健康检查接口 | |
| 243 | - | |
| 244 | -- **端点**: `GET /indexer/health` | |
| 245 | -- **描述**: 检查索引服务的健康状态 | |
| 246 | - | |
| 247 | -#### 响应格式 | |
| 248 | - | |
| 249 | -```json | |
| 250 | -{ | |
| 251 | - "status": "available", | |
| 252 | - "database": "connected", | |
| 253 | - "preloaded_data": { | |
| 254 | - "category_mappings": 150 | |
| 255 | - } | |
| 256 | -} | |
| 257 | -``` | |
| 258 | - | |
| 259 | -#### 请求示例 | |
| 260 | - | |
| 261 | -```bash | |
| 262 | -curl -X GET "http://localhost:6002/indexer/health" | |
| 263 | -``` | |
| 136 | +| 获取配置 | GET | `/admin/config` | 获取租户配置 | | |
| 137 | +| 索引统计 | GET | `/admin/stats` | 获取索引统计信息 | | |
| 264 | 138 | |
| 265 | 139 | --- |
| 266 | 140 | |
| 267 | 141 | ## 搜索接口 |
| 268 | 142 | |
| 269 | -### 接口信息 | |
| 143 | +### 3.1 接口信息 | |
| 270 | 144 | |
| 271 | 145 | - **端点**: `POST /search/` |
| 272 | 146 | - **描述**: 执行文本搜索查询,支持多语言、布尔表达式、过滤器和分面搜索 |
| 273 | 147 | |
| 274 | -### 请求参数 | |
| 148 | +### 3.2 请求参数 | |
| 275 | 149 | |
| 276 | 150 | #### 完整请求体结构 |
| 277 | 151 | |
| ... | ... | @@ -294,8 +168,6 @@ curl -X GET "http://localhost:6002/indexer/health" |
| 294 | 168 | } |
| 295 | 169 | ``` |
| 296 | 170 | |
| 297 | -**注意**: `tenant_id` 通过 HTTP Header `X-Tenant-ID` 传递,不在请求体中。 | |
| 298 | - | |
| 299 | 171 | #### 参数详细说明 |
| 300 | 172 | |
| 301 | 173 | | 参数 | 类型 | 必填 | 默认值 | 说明 | |
| ... | ... | @@ -304,22 +176,22 @@ curl -X GET "http://localhost:6002/indexer/health" |
| 304 | 176 | | `size` | integer | N | 10 | 返回结果数量(1-100) | |
| 305 | 177 | | `from` | integer | N | 0 | 分页偏移量(用于分页) | |
| 306 | 178 | | `language` | string | N | "zh" | 返回语言:`zh`(中文)或 `en`(英文)。后端会根据此参数选择对应的中英文字段返回 | |
| 307 | -| `filters` | object | N | null | 精确匹配过滤器(见下文) | | |
| 308 | -| `range_filters` | object | N | null | 数值范围过滤器(见下文) | | |
| 309 | -| `facets` | array | N | null | 分面配置(见下文) | | |
| 179 | +| `filters` | object | N | null | 精确匹配过滤器(见[过滤器详解](#33-过滤器详解)) | | |
| 180 | +| `range_filters` | object | N | null | 数值范围过滤器(见[过滤器详解](#33-过滤器详解)) | | |
| 181 | +| `facets` | array | N | null | 分面配置(见[分面配置](#34-分面配置)) | | |
| 310 | 182 | | `sort_by` | string | N | null | 排序字段名。支持:`price`(价格)、`sales`(销量)、`create_time`(创建时间)、`update_time`(更新时间)。默认按相关性排序 | |
| 311 | 183 | | `sort_order` | string | N | "desc" | 排序方向:`asc`(升序)或 `desc`(降序)。注意:`price`+`asc`=价格从低到高,`price`+`desc`=价格从高到低(后端自动映射为min_price或max_price) | |
| 312 | 184 | | `min_score` | float | N | null | 最小相关性分数阈值 | |
| 313 | -| `sku_filter_dimension` | array[string] | N | null | 子SKU筛选维度列表(店铺配置)。指定后,每个SPU下的SKU将按这些维度的组合进行分组,每个组合只返回第一个SKU。支持的值:`option1`、`option2`、`option3` 或选项名称(如 `color`、`size`)。详见下文说明 | | |
| 185 | +| `sku_filter_dimension` | array[string] | N | null | 子SKU筛选维度列表(见[SKU筛选维度](#35-sku筛选维度)) | | |
| 314 | 186 | | `debug` | boolean | N | false | 是否返回调试信息 | |
| 315 | 187 | | `user_id` | string | N | null | 用户ID(用于个性化,预留) | |
| 316 | 188 | | `session_id` | string | N | null | 会话ID(用于分析,预留) | |
| 317 | 189 | |
| 318 | -### 过滤器详解 | |
| 190 | +### 3.3 过滤器详解 | |
| 319 | 191 | |
| 320 | -#### 1. 精确匹配过滤器 (filters) | |
| 192 | +#### 3.3.1 精确匹配过滤器 (filters) | |
| 321 | 193 | |
| 322 | -用于精确匹配或多值匹配。对于普通字段,数组表示 OR 逻辑(匹配任意一个值);对于 specifications 字段,按维度分组处理(见下文)。 | |
| 194 | +用于精确匹配或多值匹配。对于普通字段,数组表示 OR 逻辑(匹配任意一个值);对于 specifications 字段,按维度分组处理。 | |
| 323 | 195 | |
| 324 | 196 | **格式**: |
| 325 | 197 | ```json |
| ... | ... | @@ -396,7 +268,7 @@ curl -X GET "http://localhost:6002/indexer/health" |
| 396 | 268 | - **不同维度**(不同的 `name`)之间是 **AND** 关系(求交集) |
| 397 | 269 | - **相同维度**(相同的 `name`)的多个值之间是 **OR** 关系(求并集) |
| 398 | 270 | |
| 399 | -**常用过滤字段**: | |
| 271 | +**常用过滤字段**(详见[常用字段列表](#83-常用字段列表)): | |
| 400 | 272 | - `category_name`: 类目名称 |
| 401 | 273 | - `category1_name`, `category2_name`, `category3_name`: 多级类目 |
| 402 | 274 | - `category_id`: 类目ID |
| ... | ... | @@ -405,7 +277,7 @@ curl -X GET "http://localhost:6002/indexer/health" |
| 405 | 277 | - `option1_name`, `option2_name`, `option3_name`: 选项名称 |
| 406 | 278 | - `specifications`: 规格过滤(嵌套字段,格式见上文) |
| 407 | 279 | |
| 408 | -#### 2. 范围过滤器 (range_filters) | |
| 280 | +#### 3.3.2 范围过滤器 (range_filters) | |
| 409 | 281 | |
| 410 | 282 | 用于数值字段的范围过滤。 |
| 411 | 283 | |
| ... | ... | @@ -435,18 +307,18 @@ curl -X GET "http://localhost:6002/indexer/health" |
| 435 | 307 | |
| 436 | 308 | **注意**: 至少需要指定一个操作符。 |
| 437 | 309 | |
| 438 | -**常用范围字段**: | |
| 310 | +**常用范围字段**(详见[常用字段列表](#83-常用字段列表)): | |
| 439 | 311 | - `min_price`: 最低价格 |
| 440 | 312 | - `max_price`: 最高价格 |
| 441 | 313 | - `compare_at_price`: 原价 |
| 442 | 314 | - `create_time`: 创建时间 |
| 443 | 315 | - `update_time`: 更新时间 |
| 444 | 316 | |
| 445 | -#### 3. 分面配置 (facets) | |
| 317 | +### 3.4 分面配置 | |
| 446 | 318 | |
| 447 | 319 | 用于生成分面统计(分组聚合),常用于构建筛选器UI。 |
| 448 | 320 | |
| 449 | -**配置格式**(对象数组): | |
| 321 | +#### 3.4.1 配置格式 | |
| 450 | 322 | |
| 451 | 323 | ```json |
| 452 | 324 | { |
| ... | ... | @@ -483,7 +355,7 @@ curl -X GET "http://localhost:6002/indexer/health" |
| 483 | 355 | } |
| 484 | 356 | ``` |
| 485 | 357 | |
| 486 | -**Facet 字段说明**: | |
| 358 | +#### 3.4.2 Facet 字段说明 | |
| 487 | 359 | |
| 488 | 360 | | 字段 | 类型 | 必填 | 默认值 | 说明 | |
| 489 | 361 | |------|------|------|--------|------| |
| ... | ... | @@ -493,22 +365,21 @@ curl -X GET "http://localhost:6002/indexer/health" |
| 493 | 365 | | `disjunctive` | bool | 否 | false | **是否支持多选模式**(见下文详细说明) | |
| 494 | 366 | | `ranges` | array | 否 | null | 范围配置(仅 `type="range"` 时需要) | |
| 495 | 367 | |
| 496 | -#### 🆕 Multi-Select Faceting(多选分面) | |
| 368 | +#### 3.4.3 Multi-Select Faceting(多选分面) | |
| 497 | 369 | |
| 498 | 370 | **重要特性**: `disjunctive` 字段控制分面的行为模式。 |
| 499 | 371 | |
| 500 | - | |
| 501 | -##### 标准模式 (disjunctive: false) | |
| 372 | +**标准模式 (disjunctive: false)**: | |
| 502 | 373 | - **行为**: 选中某个分面值后,该分面只显示选中的值 |
| 503 | 374 | - **适用场景**: 层级类目、互斥选择 |
| 504 | 375 | - **示例**: 类目下钻(玩具 > 娃娃 > 芭比) |
| 505 | 376 | |
| 506 | -##### Multi-Select 模式 (disjunctive: true) ⭐ | |
| 377 | +**Multi-Select 模式 (disjunctive: true)** ⭐: | |
| 507 | 378 | - **行为**: 选中某个分面值后,该分面仍显示所有可选项 |
| 508 | 379 | - **适用场景**: 颜色、品牌、尺码等可切换属性 |
| 509 | 380 | - **示例**: 选择了"红色"后,仍能看到"蓝色"、"绿色"等选项 |
| 510 | 381 | |
| 511 | -##### 推荐配置 | |
| 382 | +**推荐配置**: | |
| 512 | 383 | |
| 513 | 384 | | 分面类型 | disjunctive | 原因 | |
| 514 | 385 | |---------|-------------|------| |
| ... | ... | @@ -518,7 +389,7 @@ curl -X GET "http://localhost:6002/indexer/health" |
| 518 | 389 | | 类目 | `false` | 层级下钻 | |
| 519 | 390 | | 价格区间 | `false` | 互斥选择 | |
| 520 | 391 | |
| 521 | -**规格分面说明**: | |
| 392 | +#### 3.4.4 规格分面说明 | |
| 522 | 393 | |
| 523 | 394 | `specifications` 是嵌套字段,支持两种分面模式: |
| 524 | 395 | |
| ... | ... | @@ -584,13 +455,7 @@ curl -X GET "http://localhost:6002/indexer/health" |
| 584 | 455 | } |
| 585 | 456 | ``` |
| 586 | 457 | |
| 587 | -**分面配置参数**: | |
| 588 | -- `field`: 字段名(必填) | |
| 589 | -- `size`: 返回的分组数量(默认:10,范围:1-100) | |
| 590 | -- `type`: 分面类型,`terms`(分组统计)或 `range`(范围统计) | |
| 591 | -- `ranges`: 范围定义(仅当 type='range' 时需要) | |
| 592 | - | |
| 593 | -### SKU筛选维度 (sku_filter_dimension) | |
| 458 | +### 3.5 SKU筛选维度 | |
| 594 | 459 | |
| 595 | 460 | **功能说明**: |
| 596 | 461 | `sku_filter_dimension` 用于控制搜索列表页中 **每个 SPU 下方可切换的子款式(子 SKU)维度**,为字符串列表。 |
| ... | ... | @@ -630,9 +495,7 @@ curl -X GET "http://localhost:6002/indexer/health" |
| 630 | 495 | } |
| 631 | 496 | ``` |
| 632 | 497 | |
| 633 | ---- | |
| 634 | - | |
| 635 | -### 布尔表达式语法 | |
| 498 | +### 3.6 布尔表达式语法 | |
| 636 | 499 | |
| 637 | 500 | 搜索查询支持布尔表达式,提供更灵活的搜索能力。 |
| 638 | 501 | |
| ... | ... | @@ -662,63 +525,151 @@ curl -X GET "http://localhost:6002/indexer/health" |
| 662 | 525 | "玩具 AND (乐高 OR 芭比)" // 复杂查询 |
| 663 | 526 | ``` |
| 664 | 527 | |
| 665 | ---- | |
| 528 | +### 3.7 搜索建议接口 | |
| 666 | 529 | |
| 667 | -## 响应格式说明 | |
| 530 | +> ⚠️ **TODO**: 此接口当前为框架实现,功能暂未实现,仅返回空结果。接口和响应格式已经固定,可平滑扩展。 | |
| 531 | + | |
| 532 | +- **端点**: `GET /search/suggestions` | |
| 533 | +- **描述**: 返回搜索建议(自动补全/热词)。当前为框架实现,接口和响应格式已经固定,可平滑扩展。 | |
| 534 | + | |
| 535 | +#### 查询参数 | |
| 536 | + | |
| 537 | +| 参数 | 类型 | 必填 | 默认值 | 描述 | | |
| 538 | +|------|------|------|--------|------| | |
| 539 | +| `q` | string | Y | - | 查询字符串(至少 1 个字符) | | |
| 540 | +| `size` | integer | N | 5 | 返回建议数量(1-20) | | |
| 541 | +| `types` | string | N | `query` | 建议类型(逗号分隔):`query`, `product`, `category`, `brand` | | |
| 668 | 542 | |
| 669 | -### 标准响应结构 | |
| 543 | +#### 响应示例 | |
| 670 | 544 | |
| 671 | 545 | ```json |
| 672 | 546 | { |
| 673 | - "results": [ | |
| 547 | + "query": "芭", | |
| 548 | + "suggestions": [ | |
| 674 | 549 | { |
| 675 | - "spu_id": "12345", | |
| 676 | - "title": "芭比时尚娃娃", | |
| 677 | - "brief": "高品质芭比娃娃", | |
| 678 | - "description": "详细描述...", | |
| 679 | - "vendor": "美泰", | |
| 680 | - "category": "玩具", | |
| 681 | - "category_path": "玩具/娃娃/时尚", | |
| 682 | - "category_name": "时尚", | |
| 683 | - "category_id": "cat_001", | |
| 684 | - "category_level": 3, | |
| 685 | - "category1_name": "玩具", | |
| 686 | - "category2_name": "娃娃", | |
| 687 | - "category3_name": "时尚", | |
| 688 | - "tags": ["娃娃", "玩具", "女孩"], | |
| 689 | - "price": 89.99, | |
| 690 | - "compare_at_price": 129.99, | |
| 691 | - "currency": "USD", | |
| 692 | - "image_url": "https://example.com/image.jpg", | |
| 693 | - "in_stock": true, | |
| 694 | - "sku_prices": [89.99, 99.99, 109.99], | |
| 695 | - "sku_weights": [100, 150, 200], | |
| 696 | - "sku_weight_units": ["g", "g", "g"], | |
| 697 | - "total_inventory": 500, | |
| 698 | - "option1_name": "color", | |
| 699 | - "option2_name": "size", | |
| 700 | - "option3_name": null, | |
| 701 | - "specifications": [ | |
| 702 | - {"sku_id": "sku_001", "name": "color", "value": "pink"}, | |
| 703 | - {"sku_id": "sku_001", "name": "size", "value": "standard"} | |
| 704 | - ], | |
| 705 | - "skus": [ | |
| 706 | - { | |
| 707 | - "sku_id": "67890", | |
| 708 | - "price": 89.99, | |
| 709 | - "compare_at_price": 129.99, | |
| 710 | - "sku": "BARBIE-001", | |
| 711 | - "stock": 100, | |
| 712 | - "weight": 0.1, | |
| 713 | - "weight_unit": "kg", | |
| 714 | - "option1_value": "pink", | |
| 715 | - "option2_value": "standard", | |
| 716 | - "option3_value": null, | |
| 717 | - "image_src": "https://example.com/sku1.jpg" | |
| 718 | - } | |
| 719 | - ], | |
| 720 | - "relevance_score": 8.5 | |
| 721 | - } | |
| 550 | + "text": "芭比娃娃", | |
| 551 | + "type": "query", | |
| 552 | + "highlight": "<em>芭</em>比娃娃", | |
| 553 | + "popularity": 850 | |
| 554 | + } | |
| 555 | + ], | |
| 556 | + "took_ms": 5 | |
| 557 | +} | |
| 558 | +``` | |
| 559 | + | |
| 560 | +#### 请求示例 | |
| 561 | + | |
| 562 | +```bash | |
| 563 | +curl "http://localhost:6002/search/suggestions?q=芭&size=5&types=query,product" | |
| 564 | +``` | |
| 565 | + | |
| 566 | +### 3.8 即时搜索接口 | |
| 567 | + | |
| 568 | +> ⚠️ **TODO**: 此接口当前为框架实现,功能暂未实现,调用标准搜索接口。后续需要优化即时搜索性能(添加防抖/节流、实现结果缓存、简化返回字段)。 | |
| 569 | + | |
| 570 | +- **端点**: `GET /search/instant` | |
| 571 | +- **描述**: 边输入边搜索,采用轻量参数响应当前输入。底层复用标准搜索能力。 | |
| 572 | + | |
| 573 | +#### 查询参数 | |
| 574 | + | |
| 575 | +| 参数 | 类型 | 必填 | 默认值 | 描述 | | |
| 576 | +|------|------|------|--------|------| | |
| 577 | +| `q` | string | Y | - | 搜索查询(至少 2 个字符) | | |
| 578 | +| `size` | integer | N | 5 | 返回结果数量(1-20) | | |
| 579 | + | |
| 580 | +#### 请求示例 | |
| 581 | + | |
| 582 | +```bash | |
| 583 | +curl "http://localhost:6002/search/instant?q=玩具&size=5" | |
| 584 | +``` | |
| 585 | + | |
| 586 | +### 3.9 获取单个文档 | |
| 587 | + | |
| 588 | +- **端点**: `GET /search/{doc_id}` | |
| 589 | +- **描述**: 根据文档 ID 获取单个商品详情,用于点击结果后的详情页或排查问题。 | |
| 590 | + | |
| 591 | +#### 路径参数 | |
| 592 | + | |
| 593 | +| 参数 | 类型 | 描述 | | |
| 594 | +|------|------|------| | |
| 595 | +| `doc_id` | string | 商品或文档 ID | | |
| 596 | + | |
| 597 | +#### 响应示例 | |
| 598 | + | |
| 599 | +```json | |
| 600 | +{ | |
| 601 | + "id": "12345", | |
| 602 | + "source": { | |
| 603 | + "title_zh": "芭比时尚娃娃", | |
| 604 | + "min_price": 89.99, | |
| 605 | + "category1_name": "玩具" | |
| 606 | + } | |
| 607 | +} | |
| 608 | +``` | |
| 609 | + | |
| 610 | +#### 请求示例 | |
| 611 | + | |
| 612 | +```bash | |
| 613 | +curl "http://localhost:6002/search/12345" | |
| 614 | +``` | |
| 615 | + | |
| 616 | +--- | |
| 617 | + | |
| 618 | +## 响应格式说明 | |
| 619 | + | |
| 620 | +### 4.1 标准响应结构 | |
| 621 | + | |
| 622 | +```json | |
| 623 | +{ | |
| 624 | + "results": [ | |
| 625 | + { | |
| 626 | + "spu_id": "12345", | |
| 627 | + "title": "芭比时尚娃娃", | |
| 628 | + "brief": "高品质芭比娃娃", | |
| 629 | + "description": "详细描述...", | |
| 630 | + "vendor": "美泰", | |
| 631 | + "category": "玩具", | |
| 632 | + "category_path": "玩具/娃娃/时尚", | |
| 633 | + "category_name": "时尚", | |
| 634 | + "category_id": "cat_001", | |
| 635 | + "category_level": 3, | |
| 636 | + "category1_name": "玩具", | |
| 637 | + "category2_name": "娃娃", | |
| 638 | + "category3_name": "时尚", | |
| 639 | + "tags": ["娃娃", "玩具", "女孩"], | |
| 640 | + "price": 89.99, | |
| 641 | + "compare_at_price": 129.99, | |
| 642 | + "currency": "USD", | |
| 643 | + "image_url": "https://example.com/image.jpg", | |
| 644 | + "in_stock": true, | |
| 645 | + "sku_prices": [89.99, 99.99, 109.99], | |
| 646 | + "sku_weights": [100, 150, 200], | |
| 647 | + "sku_weight_units": ["g", "g", "g"], | |
| 648 | + "total_inventory": 500, | |
| 649 | + "option1_name": "color", | |
| 650 | + "option2_name": "size", | |
| 651 | + "option3_name": null, | |
| 652 | + "specifications": [ | |
| 653 | + {"sku_id": "sku_001", "name": "color", "value": "pink"}, | |
| 654 | + {"sku_id": "sku_001", "name": "size", "value": "standard"} | |
| 655 | + ], | |
| 656 | + "skus": [ | |
| 657 | + { | |
| 658 | + "sku_id": "67890", | |
| 659 | + "price": 89.99, | |
| 660 | + "compare_at_price": 129.99, | |
| 661 | + "sku": "BARBIE-001", | |
| 662 | + "stock": 100, | |
| 663 | + "weight": 0.1, | |
| 664 | + "weight_unit": "kg", | |
| 665 | + "option1_value": "pink", | |
| 666 | + "option2_value": "standard", | |
| 667 | + "option3_value": null, | |
| 668 | + "image_src": "https://example.com/sku1.jpg" | |
| 669 | + } | |
| 670 | + ], | |
| 671 | + "relevance_score": 8.5 | |
| 672 | + } | |
| 722 | 673 | ], |
| 723 | 674 | "total": 118, |
| 724 | 675 | "max_score": 8.5, |
| ... | ... | @@ -765,7 +716,7 @@ curl -X GET "http://localhost:6002/indexer/health" |
| 765 | 716 | } |
| 766 | 717 | ``` |
| 767 | 718 | |
| 768 | -### 响应字段说明 | |
| 719 | +### 4.2 响应字段说明 | |
| 769 | 720 | |
| 770 | 721 | | 字段 | 类型 | 说明 | |
| 771 | 722 | |------|------|------| |
| ... | ... | @@ -781,7 +732,7 @@ curl -X GET "http://localhost:6002/indexer/health" |
| 781 | 732 | | `query_info` | object | 查询处理信息 | |
| 782 | 733 | | `took_ms` | integer | 搜索耗时(毫秒) | |
| 783 | 734 | |
| 784 | -### SpuResult字段说明 | |
| 735 | +### 4.3 SpuResult字段说明 | |
| 785 | 736 | |
| 786 | 737 | | 字段 | 类型 | 说明 | |
| 787 | 738 | |------|------|------| |
| ... | ... | @@ -816,35 +767,255 @@ curl -X GET "http://localhost:6002/indexer/health" |
| 816 | 767 | | `skus` | array | SKU 列表 | |
| 817 | 768 | | `relevance_score` | float | 相关性分数 | |
| 818 | 769 | |
| 819 | -**多语言字段说明**: | |
| 820 | -- `title`, `brief`, `description`, `vendor`, `category_path`, `category_name` 会根据请求的 `language` 参数自动选择对应的中英文字段 | |
| 821 | -- `language="zh"`: 优先返回 `*_zh` 字段,如果为空则回退到 `*_en` 字段 | |
| 822 | -- `language="en"`: 优先返回 `*_en` 字段,如果为空则回退到 `*_zh` 字段 | |
| 770 | +### 4.4 SkuResult字段说明 | |
| 771 | + | |
| 772 | +| 字段 | 类型 | 说明 | | |
| 773 | +|------|------|------| | |
| 774 | +| `sku_id` | string | SKU ID | | |
| 775 | +| `price` | float | 价格 | | |
| 776 | +| `compare_at_price` | float | 原价 | | |
| 777 | +| `sku` | string | SKU编码(sku_code) | | |
| 778 | +| `stock` | integer | 库存数量 | | |
| 779 | +| `weight` | float | 重量 | | |
| 780 | +| `weight_unit` | string | 重量单位 | | |
| 781 | +| `option1_value` | string | 选项1取值(如color值) | | |
| 782 | +| `option2_value` | string | 选项2取值(如size值) | | |
| 783 | +| `option3_value` | string | 选项3取值 | | |
| 784 | +| `image_src` | string | SKU图片地址 | | |
| 785 | + | |
| 786 | +### 4.5 多语言字段说明 | |
| 787 | + | |
| 788 | +- `title`, `brief`, `description`, `vendor`, `category_path`, `category_name` 会根据请求的 `language` 参数自动选择对应的中英文字段 | |
| 789 | +- `language="zh"`: 优先返回 `*_zh` 字段,如果为空则回退到 `*_en` 字段 | |
| 790 | +- `language="en"`: 优先返回 `*_en` 字段,如果为空则回退到 `*_zh` 字段 | |
| 791 | + | |
| 792 | +--- | |
| 793 | + | |
| 794 | +## 索引接口 | |
| 795 | + | |
| 796 | +### 5.1 全量索引接口 | |
| 797 | + | |
| 798 | +- **端点**: `POST /indexer/bulk` | |
| 799 | +- **描述**: 将指定租户的所有SPU数据导入到ES索引 | |
| 800 | + | |
| 801 | +#### 请求参数 | |
| 802 | + | |
| 803 | +```json | |
| 804 | +{ | |
| 805 | + "tenant_id": "162", | |
| 806 | + "recreate_index": false, | |
| 807 | + "batch_size": 500 | |
| 808 | +} | |
| 809 | +``` | |
| 810 | + | |
| 811 | +| 参数 | 类型 | 必填 | 默认值 | 说明 | | |
| 812 | +|------|------|------|--------|------| | |
| 813 | +| `tenant_id` | string | Y | - | 租户ID | | |
| 814 | +| `recreate_index` | boolean | N | false | 是否重建索引(删除旧索引后创建新索引) | | |
| 815 | +| `batch_size` | integer | N | 500 | 批量导入大小 | | |
| 816 | + | |
| 817 | +#### 响应格式 | |
| 818 | + | |
| 819 | +**成功响应(200 OK)**: | |
| 820 | +```json | |
| 821 | +{ | |
| 822 | + "success": true, | |
| 823 | + "total": 1000, | |
| 824 | + "indexed": 1000, | |
| 825 | + "failed": 0, | |
| 826 | + "elapsed_time": 12.34, | |
| 827 | + "index_name": "search_products", | |
| 828 | + "tenant_id": "162" | |
| 829 | +} | |
| 830 | +``` | |
| 831 | + | |
| 832 | +**错误响应**: | |
| 833 | +- `400 Bad Request`: 参数错误 | |
| 834 | +- `503 Service Unavailable`: 服务未初始化 | |
| 835 | + | |
| 836 | +#### 请求示例 | |
| 837 | + | |
| 838 | +**首次索引(重建索引)**: | |
| 839 | +```bash | |
| 840 | +curl -X POST "http://localhost:6002/indexer/bulk" \ | |
| 841 | + -H "Content-Type: application/json" \ | |
| 842 | + -d '{ | |
| 843 | + "tenant_id": "162", | |
| 844 | + "recreate_index": true, | |
| 845 | + "batch_size": 500 | |
| 846 | + }' | |
| 847 | +``` | |
| 848 | + | |
| 849 | +**查看日志**: | |
| 850 | +```bash | |
| 851 | +# 查看API日志(包含索引操作日志) | |
| 852 | +tail -f logs/api.log | |
| 853 | + | |
| 854 | +# 或者查看所有日志文件 | |
| 855 | +tail -f logs/*.log | |
| 856 | +``` | |
| 857 | + | |
| 858 | +**增量更新(不重建索引)**: | |
| 859 | +```bash | |
| 860 | +curl -X POST "http://localhost:6002/indexer/bulk" \ | |
| 861 | + -H "Content-Type: application/json" \ | |
| 862 | + -d '{ | |
| 863 | + "tenant_id": "162", | |
| 864 | + "recreate_index": false, | |
| 865 | + "batch_size": 500 | |
| 866 | + }' | |
| 867 | +``` | |
| 868 | + | |
| 869 | +### 5.2 SPU索引接口 | |
| 870 | + | |
| 871 | +- **端点**: `POST /indexer/spus` | |
| 872 | +- **描述**: 获取SPU的ES文档数据(支持单个或批量) | |
| 873 | + | |
| 874 | +#### 请求参数 | |
| 875 | + | |
| 876 | +```json | |
| 877 | +{ | |
| 878 | + "tenant_id": "162", | |
| 879 | + "spu_ids": ["123", "456", "789"] | |
| 880 | +} | |
| 881 | +``` | |
| 882 | + | |
| 883 | +| 参数 | 类型 | 必填 | 说明 | | |
| 884 | +|------|------|------|------| | |
| 885 | +| `tenant_id` | string | Y | 租户ID | | |
| 886 | +| `spu_ids` | array[string] | Y | SPU ID列表(1-100个) | | |
| 887 | + | |
| 888 | +#### 响应格式 | |
| 889 | + | |
| 890 | +```json | |
| 891 | +{ | |
| 892 | + "success": [ | |
| 893 | + { | |
| 894 | + "spu_id": "123", | |
| 895 | + "document": { | |
| 896 | + "tenant_id": "162", | |
| 897 | + "spu_id": "123", | |
| 898 | + "title_zh": "商品标题", | |
| 899 | + ... | |
| 900 | + } | |
| 901 | + }, | |
| 902 | + { | |
| 903 | + "spu_id": "456", | |
| 904 | + "document": {...} | |
| 905 | + } | |
| 906 | + ], | |
| 907 | + "failed": [ | |
| 908 | + { | |
| 909 | + "spu_id": "789", | |
| 910 | + "error": "SPU not found or deleted" | |
| 911 | + } | |
| 912 | + ], | |
| 913 | + "total": 3, | |
| 914 | + "success_count": 2, | |
| 915 | + "failed_count": 1 | |
| 916 | +} | |
| 917 | +``` | |
| 918 | + | |
| 919 | +#### 请求示例 | |
| 920 | + | |
| 921 | +**单个SPU**: | |
| 922 | +```bash | |
| 923 | +curl -X POST "http://localhost:6002/indexer/spus" \ | |
| 924 | + -H "Content-Type: application/json" \ | |
| 925 | + -d '{ | |
| 926 | + "tenant_id": "162", | |
| 927 | + "spu_ids": ["123"] | |
| 928 | + }' | |
| 929 | +``` | |
| 930 | + | |
| 931 | +**批量SPU**: | |
| 932 | +```bash | |
| 933 | +curl -X POST "http://localhost:6002/indexer/spus" \ | |
| 934 | + -H "Content-Type: application/json" \ | |
| 935 | + -d '{ | |
| 936 | + "tenant_id": "162", | |
| 937 | + "spu_ids": ["123", "456", "789"] | |
| 938 | + }' | |
| 939 | +``` | |
| 940 | + | |
| 941 | +### 5.3 索引健康检查接口 | |
| 942 | + | |
| 943 | +- **端点**: `GET /indexer/health` | |
| 944 | +- **描述**: 检查索引服务的健康状态 | |
| 945 | + | |
| 946 | +#### 响应格式 | |
| 947 | + | |
| 948 | +```json | |
| 949 | +{ | |
| 950 | + "status": "available", | |
| 951 | + "database": "connected", | |
| 952 | + "preloaded_data": { | |
| 953 | + "category_mappings": 150 | |
| 954 | + } | |
| 955 | +} | |
| 956 | +``` | |
| 957 | + | |
| 958 | +#### 请求示例 | |
| 959 | + | |
| 960 | +```bash | |
| 961 | +curl -X GET "http://localhost:6002/indexer/health" | |
| 962 | +``` | |
| 963 | + | |
| 964 | +--- | |
| 965 | + | |
| 966 | +## 管理接口 | |
| 967 | + | |
| 968 | +### 6.1 健康检查 | |
| 969 | + | |
| 970 | +- **端点**: `GET /admin/health` | |
| 971 | +- **描述**: 检查服务与依赖(如 Elasticsearch)状态。 | |
| 972 | + | |
| 973 | +```json | |
| 974 | +{ | |
| 975 | + "status": "healthy", | |
| 976 | + "elasticsearch": "connected", | |
| 977 | + "tenant_id": "tenant1" | |
| 978 | +} | |
| 979 | +``` | |
| 980 | + | |
| 981 | +### 6.2 获取配置 | |
| 982 | + | |
| 983 | +- **端点**: `GET /admin/config` | |
| 984 | +- **描述**: 返回当前租户的脱敏配置,便于核对索引及排序表达式。 | |
| 985 | + | |
| 986 | +```json | |
| 987 | +{ | |
| 988 | + "tenant_id": "tenant1", | |
| 989 | + "tenant_name": "Tenant1 Test Instance", | |
| 990 | + "es_index_name": "search_tenant1", | |
| 991 | + "num_fields": 20, | |
| 992 | + "num_indexes": 4, | |
| 993 | + "supported_languages": ["zh", "en", "ru"], | |
| 994 | + "ranking_expression": "bm25() + 0.2*text_embedding_relevance()", | |
| 995 | + "spu_enabled": false | |
| 996 | +} | |
| 997 | +``` | |
| 998 | + | |
| 999 | +### 6.3 索引统计 | |
| 823 | 1000 | |
| 824 | -### SkuResult字段说明 | |
| 1001 | +- **端点**: `GET /admin/stats` | |
| 1002 | +- **描述**: 获取索引文档数量与磁盘大小,方便监控。 | |
| 825 | 1003 | |
| 826 | -| 字段 | 类型 | 说明 | | |
| 827 | -|------|------|------| | |
| 828 | -| `sku_id` | string | SKU ID | | |
| 829 | -| `price` | float | 价格 | | |
| 830 | -| `compare_at_price` | float | 原价 | | |
| 831 | -| `sku` | string | SKU编码(sku_code) | | |
| 832 | -| `stock` | integer | 库存数量 | | |
| 833 | -| `weight` | float | 重量 | | |
| 834 | -| `weight_unit` | string | 重量单位 | | |
| 835 | -| `option1_value` | string | 选项1取值(如color值) | | |
| 836 | -| `option2_value` | string | 选项2取值(如size值) | | |
| 837 | -| `option3_value` | string | 选项3取值 | | |
| 838 | -| `image_src` | string | SKU图片地址 | | |
| 1004 | +```json | |
| 1005 | +{ | |
| 1006 | + "index_name": "search_tenant1", | |
| 1007 | + "document_count": 10000, | |
| 1008 | + "size_mb": 523.45 | |
| 1009 | +} | |
| 1010 | +``` | |
| 839 | 1011 | |
| 840 | 1012 | --- |
| 841 | 1013 | |
| 842 | 1014 | ## 常见场景示例 |
| 843 | 1015 | |
| 844 | -### 场景1:商品列表页搜索 | |
| 845 | - | |
| 846 | -**需求**: 搜索"玩具",按价格从低到高排序,显示前20个结果 | |
| 1016 | +### 7.1 基础搜索与排序 | |
| 847 | 1017 | |
| 1018 | +**按价格从低到高排序**: | |
| 848 | 1019 | ```json |
| 849 | 1020 | { |
| 850 | 1021 | "query": "玩具", |
| ... | ... | @@ -855,8 +1026,7 @@ curl -X GET "http://localhost:6002/indexer/health" |
| 855 | 1026 | } |
| 856 | 1027 | ``` |
| 857 | 1028 | |
| 858 | -**需求**: 搜索"玩具",按价格从高到低排序 | |
| 859 | - | |
| 1029 | +**按价格从高到低排序**: | |
| 860 | 1030 | ```json |
| 861 | 1031 | { |
| 862 | 1032 | "query": "玩具", |
| ... | ... | @@ -867,8 +1037,7 @@ curl -X GET "http://localhost:6002/indexer/health" |
| 867 | 1037 | } |
| 868 | 1038 | ``` |
| 869 | 1039 | |
| 870 | -**需求**: 搜索"玩具",按销量从高到低排序 | |
| 871 | - | |
| 1040 | +**按销量从高到低排序**: | |
| 872 | 1041 | ```json |
| 873 | 1042 | { |
| 874 | 1043 | "query": "玩具", |
| ... | ... | @@ -879,8 +1048,7 @@ curl -X GET "http://localhost:6002/indexer/health" |
| 879 | 1048 | } |
| 880 | 1049 | ``` |
| 881 | 1050 | |
| 882 | -**需求**: 搜索"玩具",按默认(相关性)排序 | |
| 883 | - | |
| 1051 | +**按默认(相关性)排序**: | |
| 884 | 1052 | ```json |
| 885 | 1053 | { |
| 886 | 1054 | "query": "玩具", |
| ... | ... | @@ -889,34 +1057,36 @@ curl -X GET "http://localhost:6002/indexer/health" |
| 889 | 1057 | } |
| 890 | 1058 | ``` |
| 891 | 1059 | |
| 892 | -### 场景2:SKU筛选(按维度过滤) | |
| 1060 | +### 7.2 过滤搜索 | |
| 893 | 1061 | |
| 894 | -**需求**: 搜索"芭比娃娃",每个SPU下按颜色筛选,每种颜色只显示一个SKU | |
| 1062 | +**需求**: 搜索"玩具",筛选类目为"益智玩具",价格在50-200之间 | |
| 895 | 1063 | |
| 896 | 1064 | ```json |
| 897 | 1065 | { |
| 898 | - "query": "芭比娃娃", | |
| 1066 | + "query": "玩具", | |
| 899 | 1067 | "size": 20, |
| 900 | - "sku_filter_dimension": "color" | |
| 1068 | + "language": "zh", | |
| 1069 | + "filters": { | |
| 1070 | + "category_name": "益智玩具" | |
| 1071 | + }, | |
| 1072 | + "range_filters": { | |
| 1073 | + "min_price": { | |
| 1074 | + "gte": 50, | |
| 1075 | + "lte": 200 | |
| 1076 | + } | |
| 1077 | + } | |
| 901 | 1078 | } |
| 902 | 1079 | ``` |
| 903 | 1080 | |
| 904 | -**说明**: | |
| 905 | -- 如果 `option1_name` 为 `"color"`,则使用 `sku_filter_dimension: "color"` 可以按颜色分组 | |
| 906 | -- 每个SPU下,每种颜色只会返回第一个SKU | |
| 907 | -- 如果维度不匹配,返回所有SKU(不进行过滤) | |
| 908 | - | |
| 909 | -### 场景3:带筛选的商品搜索 | |
| 910 | - | |
| 911 | -**需求**: 搜索"玩具",筛选类目为"益智玩具",价格在50-200之间 | |
| 1081 | +**需求**: 搜索"手机",筛选多个品牌,价格范围 | |
| 912 | 1082 | |
| 913 | 1083 | ```json |
| 914 | 1084 | { |
| 915 | - "query": "玩具", | |
| 1085 | + "query": "手机", | |
| 916 | 1086 | "size": 20, |
| 917 | 1087 | "language": "zh", |
| 918 | 1088 | "filters": { |
| 919 | - "category_name": "益智玩具" | |
| 1089 | + "vendor_zh.keyword": ["品牌A", "品牌B"] | |
| 920 | 1090 | }, |
| 921 | 1091 | "range_filters": { |
| 922 | 1092 | "min_price": { |
| ... | ... | @@ -927,7 +1097,7 @@ curl -X GET "http://localhost:6002/indexer/health" |
| 927 | 1097 | } |
| 928 | 1098 | ``` |
| 929 | 1099 | |
| 930 | -### 场景4:带分面的商品搜索 | |
| 1100 | +### 7.3 分面搜索 | |
| 931 | 1101 | |
| 932 | 1102 | **需求**: 搜索"玩具",获取类目和规格的分面统计,用于构建筛选器 |
| 933 | 1103 | |
| ... | ... | @@ -944,31 +1114,15 @@ curl -X GET "http://localhost:6002/indexer/health" |
| 944 | 1114 | } |
| 945 | 1115 | ``` |
| 946 | 1116 | |
| 947 | -### 场景5:多条件组合搜索 | |
| 948 | - | |
| 949 | -**需求**: 搜索"手机",筛选多个品牌,价格范围,并获取分面统计 | |
| 1117 | +**需求**: 搜索"手机",获取价格区间和规格的分面统计 | |
| 950 | 1118 | |
| 951 | 1119 | ```json |
| 952 | 1120 | { |
| 953 | 1121 | "query": "手机", |
| 954 | 1122 | "size": 20, |
| 955 | 1123 | "language": "zh", |
| 956 | - "filters": { | |
| 957 | - "vendor_zh.keyword": ["品牌A", "品牌B"] | |
| 958 | - }, | |
| 959 | - "range_filters": { | |
| 960 | - "min_price": { | |
| 961 | - "gte": 50, | |
| 962 | - "lte": 200 | |
| 963 | - } | |
| 964 | - }, | |
| 965 | 1124 | "facets": [ |
| 966 | 1125 | { |
| 967 | - "field": "category1_name", | |
| 968 | - "size": 15, | |
| 969 | - "type": "terms" | |
| 970 | - }, | |
| 971 | - { | |
| 972 | 1126 | "field": "min_price", |
| 973 | 1127 | "type": "range", |
| 974 | 1128 | "ranges": [ |
| ... | ... | @@ -983,13 +1137,11 @@ curl -X GET "http://localhost:6002/indexer/health" |
| 983 | 1137 | "size": 10, |
| 984 | 1138 | "type": "terms" |
| 985 | 1139 | } |
| 986 | - ], | |
| 987 | - "sort_by": "min_price", | |
| 988 | - "sort_order": "asc" | |
| 1140 | + ] | |
| 989 | 1141 | } |
| 990 | 1142 | ``` |
| 991 | 1143 | |
| 992 | -### 场景6:规格过滤搜索 | |
| 1144 | +### 7.4 规格过滤与分面 | |
| 993 | 1145 | |
| 994 | 1146 | **需求**: 搜索"手机",筛选color为"white"的商品 |
| 995 | 1147 | |
| ... | ... | @@ -1007,8 +1159,6 @@ curl -X GET "http://localhost:6002/indexer/health" |
| 1007 | 1159 | } |
| 1008 | 1160 | ``` |
| 1009 | 1161 | |
| 1010 | -### 场景7:多个规格过滤(不同维度AND,相同维度OR) | |
| 1011 | - | |
| 1012 | 1162 | **需求**: 搜索"手机",筛选color为"white"且size为"256GB"的商品 |
| 1013 | 1163 | |
| 1014 | 1164 | ```json |
| ... | ... | @@ -1043,8 +1193,6 @@ curl -X GET "http://localhost:6002/indexer/health" |
| 1043 | 1193 | } |
| 1044 | 1194 | ``` |
| 1045 | 1195 | |
| 1046 | -### 场景8:规格分面搜索 | |
| 1047 | - | |
| 1048 | 1196 | **需求**: 搜索"手机",获取所有规格的分面统计 |
| 1049 | 1197 | |
| 1050 | 1198 | ```json |
| ... | ... | @@ -1072,8 +1220,6 @@ curl -X GET "http://localhost:6002/indexer/health" |
| 1072 | 1220 | } |
| 1073 | 1221 | ``` |
| 1074 | 1222 | |
| 1075 | -### 场景9:组合过滤和分面 | |
| 1076 | - | |
| 1077 | 1223 | **需求**: 搜索"手机",筛选类目和规格,并获取对应的分面统计 |
| 1078 | 1224 | |
| 1079 | 1225 | ```json |
| ... | ... | @@ -1097,172 +1243,43 @@ curl -X GET "http://localhost:6002/indexer/health" |
| 1097 | 1243 | } |
| 1098 | 1244 | ``` |
| 1099 | 1245 | |
| 1100 | -### 场景10:布尔表达式搜索 | |
| 1101 | - | |
| 1102 | -**需求**: 搜索包含"手机"和"智能"的商品,排除"二手" | |
| 1103 | - | |
| 1104 | -```json | |
| 1105 | -{ | |
| 1106 | - "query": "手机 AND 智能 ANDNOT 二手", | |
| 1107 | - "size": 20 | |
| 1108 | -} | |
| 1109 | -``` | |
| 1110 | - | |
| 1111 | -### 场景11:分页查询 | |
| 1246 | +### 7.5 SKU筛选 | |
| 1112 | 1247 | |
| 1113 | -**需求**: 获取第2页结果(每页20条) | |
| 1248 | +**需求**: 搜索"芭比娃娃",每个SPU下按颜色筛选,每种颜色只显示一个SKU | |
| 1114 | 1249 | |
| 1115 | 1250 | ```json |
| 1116 | 1251 | { |
| 1117 | - "query": "手机", | |
| 1252 | + "query": "芭比娃娃", | |
| 1118 | 1253 | "size": 20, |
| 1119 | - "from": 20 | |
| 1120 | -} | |
| 1121 | -``` | |
| 1122 | - | |
| 1123 | ---- | |
| 1124 | - | |
| 1125 | ---- | |
| 1126 | - | |
| 1127 | -## 其他接口 | |
| 1128 | - | |
| 1129 | -### 搜索建议(框架) | |
| 1130 | - | |
| 1131 | -- **端点**: `GET /search/suggestions` | |
| 1132 | -- **描述**: 返回搜索建议(自动补全/热词)。当前为框架实现,接口和响应格式已经固定,可平滑扩展。 | |
| 1133 | - | |
| 1134 | -#### 查询参数 | |
| 1135 | - | |
| 1136 | -| 参数 | 类型 | 必填 | 默认值 | 描述 | | |
| 1137 | -|------|------|------|--------|------| | |
| 1138 | -| `q` | string | Y | - | 查询字符串(至少 1 个字符) | | |
| 1139 | -| `size` | integer | N | 5 | 返回建议数量(1-20) | | |
| 1140 | -| `types` | string | N | `query` | 建议类型(逗号分隔):`query`, `product`, `category`, `brand` | | |
| 1141 | - | |
| 1142 | -#### 响应示例 | |
| 1143 | - | |
| 1144 | -```json | |
| 1145 | -{ | |
| 1146 | - "query": "芭", | |
| 1147 | - "suggestions": [ | |
| 1148 | - { | |
| 1149 | - "text": "芭比娃娃", | |
| 1150 | - "type": "query", | |
| 1151 | - "highlight": "<em>芭</em>比娃娃", | |
| 1152 | - "popularity": 850 | |
| 1153 | - } | |
| 1154 | - ], | |
| 1155 | - "took_ms": 5 | |
| 1156 | -} | |
| 1157 | -``` | |
| 1158 | - | |
| 1159 | -#### 请求示例 | |
| 1160 | - | |
| 1161 | -```bash | |
| 1162 | -curl "http://localhost:6002/search/suggestions?q=芭&size=5&types=query,product" | |
| 1163 | -``` | |
| 1164 | - | |
| 1165 | ---- | |
| 1166 | - | |
| 1167 | -### 即时搜索(框架) | |
| 1168 | - | |
| 1169 | -- **端点**: `GET /search/instant` | |
| 1170 | -- **描述**: 边输入边搜索,采用轻量参数响应当前输入。底层复用标准搜索能力。 | |
| 1171 | - | |
| 1172 | -#### 查询参数 | |
| 1173 | - | |
| 1174 | -| 参数 | 类型 | 必填 | 默认值 | 描述 | | |
| 1175 | -|------|------|------|--------|------| | |
| 1176 | -| `q` | string | Y | - | 搜索查询(至少 2 个字符) | | |
| 1177 | -| `size` | integer | N | 5 | 返回结果数量(1-20) | | |
| 1178 | - | |
| 1179 | -#### 请求示例 | |
| 1180 | - | |
| 1181 | -```bash | |
| 1182 | -curl "http://localhost:6002/search/instant?q=玩具&size=5" | |
| 1183 | -``` | |
| 1184 | - | |
| 1185 | ---- | |
| 1186 | - | |
| 1187 | -### 获取单个文档 | |
| 1188 | - | |
| 1189 | -- **端点**: `GET /search/{doc_id}` | |
| 1190 | -- **描述**: 根据文档 ID 获取单个商品详情,用于点击结果后的详情页或排查问题。 | |
| 1191 | - | |
| 1192 | -#### 路径参数 | |
| 1193 | - | |
| 1194 | -| 参数 | 类型 | 描述 | | |
| 1195 | -|------|------|------| | |
| 1196 | -| `doc_id` | string | 商品或文档 ID | | |
| 1197 | - | |
| 1198 | -#### 响应示例 | |
| 1199 | - | |
| 1200 | -```json | |
| 1201 | -{ | |
| 1202 | - "id": "12345", | |
| 1203 | - "source": { | |
| 1204 | - "title_zh": "芭比时尚娃娃", | |
| 1205 | - "min_price": 89.99, | |
| 1206 | - "category1_name": "玩具" | |
| 1207 | - } | |
| 1208 | -} | |
| 1209 | -``` | |
| 1210 | - | |
| 1211 | -#### 请求示例 | |
| 1212 | - | |
| 1213 | -```bash | |
| 1214 | -curl "http://localhost:6002/search/12345" | |
| 1215 | -``` | |
| 1216 | - | |
| 1217 | ---- | |
| 1218 | - | |
| 1219 | -## 管理接口 | |
| 1220 | - | |
| 1221 | -### 健康检查 | |
| 1222 | - | |
| 1223 | -- **端点**: `GET /admin/health` | |
| 1224 | -- **描述**: 检查服务与依赖(如 Elasticsearch)状态。 | |
| 1225 | - | |
| 1226 | -```json | |
| 1227 | -{ | |
| 1228 | - "status": "healthy", | |
| 1229 | - "elasticsearch": "connected", | |
| 1230 | - "tenant_id": "tenant1" | |
| 1254 | + "sku_filter_dimension": ["color"] | |
| 1231 | 1255 | } |
| 1232 | 1256 | ``` |
| 1233 | 1257 | |
| 1234 | ---- | |
| 1258 | +**说明**: | |
| 1259 | +- 如果 `option1_name` 为 `"color"`,则使用 `sku_filter_dimension: ["color"]` 可以按颜色分组 | |
| 1260 | +- 每个SPU下,每种颜色只会返回第一个SKU | |
| 1261 | +- 如果维度不匹配,返回所有SKU(不进行过滤) | |
| 1235 | 1262 | |
| 1236 | -### 获取配置 | |
| 1263 | +### 7.6 布尔表达式搜索 | |
| 1237 | 1264 | |
| 1238 | -- **端点**: `GET /admin/config` | |
| 1239 | -- **描述**: 返回当前租户的脱敏配置,便于核对索引及排序表达式。 | |
| 1265 | +**需求**: 搜索包含"手机"和"智能"的商品,排除"二手" | |
| 1240 | 1266 | |
| 1241 | 1267 | ```json |
| 1242 | 1268 | { |
| 1243 | - "tenant_id": "tenant1", | |
| 1244 | - "tenant_name": "Tenant1 Test Instance", | |
| 1245 | - "es_index_name": "search_tenant1", | |
| 1246 | - "num_fields": 20, | |
| 1247 | - "num_indexes": 4, | |
| 1248 | - "supported_languages": ["zh", "en", "ru"], | |
| 1249 | - "ranking_expression": "bm25() + 0.2*text_embedding_relevance()", | |
| 1250 | - "spu_enabled": false | |
| 1269 | + "query": "手机 AND 智能 ANDNOT 二手", | |
| 1270 | + "size": 20 | |
| 1251 | 1271 | } |
| 1252 | 1272 | ``` |
| 1253 | 1273 | |
| 1254 | ---- | |
| 1255 | - | |
| 1256 | -### 索引统计 | |
| 1274 | +### 7.7 分页查询 | |
| 1257 | 1275 | |
| 1258 | -- **端点**: `GET /admin/stats` | |
| 1259 | -- **描述**: 获取索引文档数量与磁盘大小,方便监控。 | |
| 1276 | +**需求**: 获取第2页结果(每页20条) | |
| 1260 | 1277 | |
| 1261 | 1278 | ```json |
| 1262 | 1279 | { |
| 1263 | - "index_name": "search_tenant1", | |
| 1264 | - "document_count": 10000, | |
| 1265 | - "size_mb": 523.45 | |
| 1280 | + "query": "手机", | |
| 1281 | + "size": 20, | |
| 1282 | + "from": 20 | |
| 1266 | 1283 | } |
| 1267 | 1284 | ``` |
| 1268 | 1285 | |
| ... | ... | @@ -1270,7 +1287,7 @@ curl "http://localhost:6002/search/12345" |
| 1270 | 1287 | |
| 1271 | 1288 | ## 数据模型 |
| 1272 | 1289 | |
| 1273 | -### 商品字段 | |
| 1290 | +### 8.1 商品字段定义 | |
| 1274 | 1291 | |
| 1275 | 1292 | | 字段名 | 类型 | 描述 | |
| 1276 | 1293 | |--------|------|------| |
| ... | ... | @@ -1303,11 +1320,20 @@ curl "http://localhost:6002/search/12345" |
| 1303 | 1320 | |
| 1304 | 1321 | > 所有租户共享统一的索引结构。文本字段支持中英文双语,后端根据 `language` 参数自动选择对应字段返回。 |
| 1305 | 1322 | |
| 1306 | ---- | |
| 1323 | +### 8.2 字段类型速查 | |
| 1307 | 1324 | |
| 1308 | -## 附录 | |
| 1325 | +| 类型 | ES Mapping | 用途 | | |
| 1326 | +|------|------------|------| | |
| 1327 | +| `text` | `text` | 全文检索(支持中英文分析器) | | |
| 1328 | +| `keyword` | `keyword` | 精确匹配、聚合、排序 | | |
| 1329 | +| `integer` | `integer` | 整数 | | |
| 1330 | +| `long` | `long` | 长整数 | | |
| 1331 | +| `float` | `float` | 浮点数 | | |
| 1332 | +| `date` | `date` | 日期时间 | | |
| 1333 | +| `nested` | `nested` | 嵌套对象(specifications, skus, image_embedding) | | |
| 1334 | +| `dense_vector` | `dense_vector` | 向量字段(title_embedding,仅用于搜索) | | |
| 1309 | 1335 | |
| 1310 | -### 常用字段列表 | |
| 1336 | +### 8.3 常用字段列表 | |
| 1311 | 1337 | |
| 1312 | 1338 | #### 过滤字段 |
| 1313 | 1339 | |
| ... | ... | @@ -1317,6 +1343,7 @@ curl "http://localhost:6002/search/12345" |
| 1317 | 1343 | - `vendor_zh.keyword`, `vendor_en.keyword`: 供应商/品牌(使用keyword子字段) |
| 1318 | 1344 | - `tags`: 标签(keyword类型) |
| 1319 | 1345 | - `option1_name`, `option2_name`, `option3_name`: 选项名称 |
| 1346 | +- `specifications`: 规格过滤(嵌套字段,格式见[过滤器详解](#33-过滤器详解)) | |
| 1320 | 1347 | |
| 1321 | 1348 | #### 范围字段 |
| 1322 | 1349 | |
| ... | ... | @@ -1338,26 +1365,13 @@ curl "http://localhost:6002/search/12345" |
| 1338 | 1365 | - `sort_by: "price"` + `sort_order: "asc"` → 按 `min_price` 升序(价格从低到高) |
| 1339 | 1366 | - `sort_by: "price"` + `sort_order: "desc"` → 按 `max_price` 降序(价格从高到低) |
| 1340 | 1367 | |
| 1341 | -### 支持的分析器 | |
| 1368 | +### 8.4 支持的分析器 | |
| 1342 | 1369 | |
| 1343 | 1370 | | 分析器 | 语言 | 描述 | |
| 1344 | 1371 | |--------|------|------| |
| 1345 | 1372 | | `index_ansj` | 中文 | 中文索引分析器(用于中文字段) | |
| 1346 | 1373 | | `query_ansj` | 中文 | 中文查询分析器(用于中文字段) | |
| 1347 | -| `hanlp_index`(暂不支持) | 中文 | 中文索引分析器(用于中文字段) | | |
| 1348 | -| `hanlp_standard`(暂不支持) | 中文 | 中文查询分析器(用于中文字段) | | |
| 1374 | +| `hanlp_index` ⚠️ TODO(暂不支持) | 中文 | 中文索引分析器(用于中文字段) | | |
| 1375 | +| `hanlp_standard` ⚠️ TODO(暂不支持) | 中文 | 中文查询分析器(用于中文字段) | | |
| 1349 | 1376 | | `english` | 英文 | 标准英文分析器(用于英文字段) | |
| 1350 | 1377 | | `lowercase` | - | 小写标准化器(用于keyword子字段) | |
| 1351 | - | |
| 1352 | -### 字段类型速查 | |
| 1353 | - | |
| 1354 | -| 类型 | ES Mapping | 用途 | | |
| 1355 | -|------|------------|------| | |
| 1356 | -| `text` | `text` | 全文检索(支持中英文分析器) | | |
| 1357 | -| `keyword` | `keyword` | 精确匹配、聚合、排序 | | |
| 1358 | -| `integer` | `integer` | 整数 | | |
| 1359 | -| `long` | `long` | 长整数 | | |
| 1360 | -| `float` | `float` | 浮点数 | | |
| 1361 | -| `date` | `date` | 日期时间 | | |
| 1362 | -| `nested` | `nested` | 嵌套对象(specifications, skus, image_embedding) | | |
| 1363 | -| `dense_vector` | `dense_vector` | 向量字段(title_embedding,仅用于搜索) | | ... | ... |