Commit 11237cf2218f281a55e60066a28c1f035f33ef7f

Authored by tangwang
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 &quot;http://localhost:6002/indexer/health&quot;
765 716 }
766 717 ```
767 718  
768   -### 响应字段说明
  719 +### 4.2 响应字段说明
769 720  
770 721 | 字段 | 类型 | 说明 |
771 722 |------|------|------|
... ... @@ -781,7 +732,7 @@ curl -X GET &quot;http://localhost:6002/indexer/health&quot;
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 &quot;http://localhost:6002/indexer/health&quot;
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 &quot;http://localhost:6002/indexer/health&quot;
855 1026 }
856 1027 ```
857 1028  
858   -**需求**: 搜索"玩具",按价格从高到低排序
859   -
  1029 +**按价格从高到低排序**:
860 1030 ```json
861 1031 {
862 1032 "query": "玩具",
... ... @@ -867,8 +1037,7 @@ curl -X GET &quot;http://localhost:6002/indexer/health&quot;
867 1037 }
868 1038 ```
869 1039  
870   -**需求**: 搜索"玩具",按销量从高到低排序
871   -
  1040 +**按销量从高到低排序**:
872 1041 ```json
873 1042 {
874 1043 "query": "玩具",
... ... @@ -879,8 +1048,7 @@ curl -X GET &quot;http://localhost:6002/indexer/health&quot;
879 1048 }
880 1049 ```
881 1050  
882   -**需求**: 搜索"玩具",按默认(相关性)排序
883   -
  1051 +**按默认(相关性)排序**:
884 1052 ```json
885 1053 {
886 1054 "query": "玩具",
... ... @@ -889,34 +1057,36 @@ curl -X GET &quot;http://localhost:6002/indexer/health&quot;
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 &quot;http://localhost:6002/indexer/health&quot;
927 1097 }
928 1098 ```
929 1099  
930   -### 场景4:带分面的商品搜索
  1100 +### 7.3 分面搜索
931 1101  
932 1102 **需求**: 搜索"玩具",获取类目和规格的分面统计,用于构建筛选器
933 1103  
... ... @@ -944,31 +1114,15 @@ curl -X GET &quot;http://localhost:6002/indexer/health&quot;
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 &quot;http://localhost:6002/indexer/health&quot;
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 &quot;http://localhost:6002/indexer/health&quot;
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 &quot;http://localhost:6002/indexer/health&quot;
1043 1193 }
1044 1194 ```
1045 1195  
1046   -### 场景8:规格分面搜索
1047   -
1048 1196 **需求**: 搜索"手机",获取所有规格的分面统计
1049 1197  
1050 1198 ```json
... ... @@ -1072,8 +1220,6 @@ curl -X GET &quot;http://localhost:6002/indexer/health&quot;
1072 1220 }
1073 1221 ```
1074 1222  
1075   -### 场景9:组合过滤和分面
1076   -
1077 1223 **需求**: 搜索"手机",筛选类目和规格,并获取对应的分面统计
1078 1224  
1079 1225 ```json
... ... @@ -1097,172 +1243,43 @@ curl -X GET &quot;http://localhost:6002/indexer/health&quot;
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 &quot;http://localhost:6002/search/12345&quot;
1270 1287  
1271 1288 ## 数据模型
1272 1289  
1273   -### 商品字段
  1290 +### 8.1 商品字段定义
1274 1291  
1275 1292 | 字段名 | 类型 | 描述 |
1276 1293 |--------|------|------|
... ... @@ -1303,11 +1320,20 @@ curl &quot;http://localhost:6002/search/12345&quot;
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 &quot;http://localhost:6002/search/12345&quot;
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 &quot;http://localhost:6002/search/12345&quot;
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,仅用于搜索) |
... ...