diff --git a/docs/搜索API对接指南.md b/docs/搜索API对接指南.md
index 0a99a34..60d66ce 100644
--- a/docs/搜索API对接指南.md
+++ b/docs/搜索API对接指南.md
@@ -5,16 +5,61 @@
## 目录
1. [快速开始](#快速开始)
+ - 1.1 [基础信息](#11-基础信息)
+ - 1.2 [最简单的搜索请求](#12-最简单的搜索请求)
+ - 1.3 [带过滤与分页的搜索](#13-带过滤与分页的搜索)
+ - 1.4 [开启分面的搜索](#14-开启分面的搜索)
+
2. [接口概览](#接口概览)
+
3. [搜索接口](#搜索接口)
+ - 3.1 [接口信息](#31-接口信息)
+ - 3.2 [请求参数](#32-请求参数)
+ - 3.3 [过滤器详解](#33-过滤器详解)
+ - 3.4 [分面配置](#34-分面配置)
+ - 3.5 [SKU筛选维度](#35-sku筛选维度)
+ - 3.6 [布尔表达式语法](#36-布尔表达式语法)
+ - 3.7 [搜索建议接口](#37-搜索建议接口)
+ - 3.8 [即时搜索接口](#38-即时搜索接口)
+ - 3.9 [获取单个文档](#39-获取单个文档)
+
4. [响应格式说明](#响应格式说明)
-5. [常见场景示例](#常见场景示例)
+ - 4.1 [标准响应结构](#41-标准响应结构)
+ - 4.2 [响应字段说明](#42-响应字段说明)
+ - 4.3 [SpuResult字段说明](#43-spuresult字段说明)
+ - 4.4 [SkuResult字段说明](#44-skuresult字段说明)
+ - 4.5 [多语言字段说明](#45-多语言字段说明)
+
+5. [索引接口](#索引接口)
+ - 5.1 [全量索引接口](#51-全量索引接口)
+ - 5.2 [SPU索引接口](#52-spu索引接口)
+ - 5.3 [索引健康检查接口](#53-索引健康检查接口)
+
+6. [管理接口](#管理接口)
+ - 6.1 [健康检查](#61-健康检查)
+ - 6.2 [获取配置](#62-获取配置)
+ - 6.3 [索引统计](#63-索引统计)
+
+7. [常见场景示例](#常见场景示例)
+ - 7.1 [基础搜索与排序](#71-基础搜索与排序)
+ - 7.2 [过滤搜索](#72-过滤搜索)
+ - 7.3 [分面搜索](#73-分面搜索)
+ - 7.4 [规格过滤与分面](#74-规格过滤与分面)
+ - 7.5 [SKU筛选](#75-sku筛选)
+ - 7.6 [布尔表达式搜索](#76-布尔表达式搜索)
+ - 7.7 [分页查询](#77-分页查询)
+
+8. [数据模型](#数据模型)
+ - 8.1 [商品字段定义](#81-商品字段定义)
+ - 8.2 [字段类型速查](#82-字段类型速查)
+ - 8.3 [常用字段列表](#83-常用字段列表)
+ - 8.4 [支持的分析器](#84-支持的分析器)
---
## 快速开始
-### 基础信息
+### 1.1 基础信息
- **Base URL**: `http://your-domain:6002` 或 `http://120.76.41.98:6002`
- **协议**: HTTP/HTTPS
@@ -22,7 +67,9 @@
- **字符编码**: UTF-8
- **请求方法**: POST(搜索接口)
-### 最简单的搜索请求
+**重要提示**: `tenant_id` 通过 HTTP Header `X-Tenant-ID` 传递,不在请求体中。
+
+### 1.2 最简单的搜索请求
```bash
curl -X POST "http://120.76.41.98:6002/search/" \
@@ -31,7 +78,7 @@ curl -X POST "http://120.76.41.98:6002/search/" \
-d '{"query": "芭比娃娃"}'
```
-### curl示例:带过滤与分页
+### 1.3 带过滤与分页的搜索
```bash
curl -X POST "http://120.76.41.98:6002/search/" \
@@ -41,21 +88,21 @@ curl -X POST "http://120.76.41.98:6002/search/" \
"query": "芭比娃娃",
"size": 5,
"from": 10,
- "range_filters": {
- "min_price": {
- "gte": 50,
- "lte": 200
+ "range_filters": {
+ "min_price": {
+ "gte": 50,
+ "lte": 200
+ },
+ "create_time": {
+ "gte": "2020-01-01T00:00:00Z"
+ }
},
- "create_time": {
- "gte": "2020-01-01T00:00:00Z"
- }
- },
"sort_by": "price",
"sort_order": "asc"
}'
```
-### curl示例:开启分面
+### 1.4 开启分面的搜索
```bash
curl -X POST "http://120.76.41.98:6002/search/" \
@@ -79,199 +126,26 @@ curl -X POST "http://120.76.41.98:6002/search/" \
| 接口 | HTTP Method | Endpoint | 说明 |
|------|------|------|------|
| 搜索 | POST | `/search/` | 执行搜索查询 |
+| 搜索建议 | GET | `/search/suggestions` | 搜索建议(框架,暂未实现) ⚠️ TODO |
+| 即时搜索 | GET | `/search/instant` | 边输入边搜索(框架) ⚠️ TODO |
+| 获取文档 | GET | `/search/{doc_id}` | 获取单个文档 |
| 全量索引 | POST | `/indexer/bulk` | 全量索引接口 |
| SPU索引 | POST | `/indexer/spus` | 获取SPU文档(支持单个或批量) |
| 索引健康检查 | GET | `/indexer/health` | 检查索引服务状态 |
-| 搜索建议(框架,暂未实现) | GET | `/search/suggestions` | 搜索建议 |
-| 获取文档 | GET | `/search/{doc_id}` | 获取单个文档 |
| 健康检查 | GET | `/admin/health` | 服务健康检查 |
-
----
-
-## 索引接口
-
-### 全量索引接口
-
-- **端点**: `POST /indexer/bulk`
-- **描述**: 将指定租户的所有SPU数据导入到ES索引
-
-#### 请求参数
-
-```json
-{
- "tenant_id": "162",
- "recreate_index": false,
- "batch_size": 500
-}
-```
-
-| 参数 | 类型 | 必填 | 默认值 | 说明 |
-|------|------|------|--------|------|
-| `tenant_id` | string | Y | - | 租户ID |
-| `recreate_index` | boolean | N | false | 是否重建索引(删除旧索引后创建新索引) |
-| `batch_size` | integer | N | 500 | 批量导入大小 |
-
-#### 响应格式
-
-**成功响应(200 OK)**:
-```json
-{
- "success": true,
- "total": 1000,
- "indexed": 1000,
- "failed": 0,
- "elapsed_time": 12.34,
- "index_name": "search_products",
- "tenant_id": "162"
-}
-```
-
-**错误响应**:
-- `400 Bad Request`: 参数错误
-- `503 Service Unavailable`: 服务未初始化
-
-#### 请求示例
-
-**首次索引(重建索引)**:
-```bash
-curl -X POST "http://localhost:6002/indexer/bulk" \
- -H "Content-Type: application/json" \
- -d '{
- "tenant_id": "162",
- "recreate_index": true,
- "batch_size": 500
- }'
-```
-
-**查看日志**:
-```bash
-# 查看API日志(包含索引操作日志)
-tail -f logs/api.log
-
-# 或者查看所有日志文件
-tail -f logs/*.log
-```
-
-**增量更新(不重建索引)**:
-```bash
-curl -X POST "http://localhost:6002/indexer/bulk" \
- -H "Content-Type: application/json" \
- -d '{
- "tenant_id": "162",
- "recreate_index": false,
- "batch_size": 500
- }'
-```
-
----
-
-### SPU索引接口
-
-- **端点**: `POST /indexer/spus`
-- **描述**: 获取SPU的ES文档数据(支持单个或批量)
-
-#### 请求参数
-
-```json
-{
- "tenant_id": "162",
- "spu_ids": ["123", "456", "789"]
-}
-```
-
-| 参数 | 类型 | 必填 | 说明 |
-|------|------|------|------|
-| `tenant_id` | string | Y | 租户ID |
-| `spu_ids` | array[string] | Y | SPU ID列表(1-100个) |
-
-#### 响应格式
-
-```json
-{
- "success": [
- {
- "spu_id": "123",
- "document": {
- "tenant_id": "162",
- "spu_id": "123",
- "title_zh": "商品标题",
- ...
- }
- },
- {
- "spu_id": "456",
- "document": {...}
- }
- ],
- "failed": [
- {
- "spu_id": "789",
- "error": "SPU not found or deleted"
- }
- ],
- "total": 3,
- "success_count": 2,
- "failed_count": 1
-}
-```
-
-#### 请求示例
-
-**单个SPU**:
-```bash
-curl -X POST "http://localhost:6002/indexer/spus" \
- -H "Content-Type: application/json" \
- -d '{
- "tenant_id": "162",
- "spu_ids": ["123"]
- }'
-```
-
-**批量SPU**:
-```bash
-curl -X POST "http://localhost:6002/indexer/spus" \
- -H "Content-Type: application/json" \
- -d '{
- "tenant_id": "162",
- "spu_ids": ["123", "456", "789"]
- }'
-```
-
----
-
-### 索引健康检查接口
-
-- **端点**: `GET /indexer/health`
-- **描述**: 检查索引服务的健康状态
-
-#### 响应格式
-
-```json
-{
- "status": "available",
- "database": "connected",
- "preloaded_data": {
- "category_mappings": 150
- }
-}
-```
-
-#### 请求示例
-
-```bash
-curl -X GET "http://localhost:6002/indexer/health"
-```
+| 获取配置 | GET | `/admin/config` | 获取租户配置 |
+| 索引统计 | GET | `/admin/stats` | 获取索引统计信息 |
---
## 搜索接口
-### 接口信息
+### 3.1 接口信息
- **端点**: `POST /search/`
- **描述**: 执行文本搜索查询,支持多语言、布尔表达式、过滤器和分面搜索
-### 请求参数
+### 3.2 请求参数
#### 完整请求体结构
@@ -294,8 +168,6 @@ curl -X GET "http://localhost:6002/indexer/health"
}
```
-**注意**: `tenant_id` 通过 HTTP Header `X-Tenant-ID` 传递,不在请求体中。
-
#### 参数详细说明
| 参数 | 类型 | 必填 | 默认值 | 说明 |
@@ -304,22 +176,22 @@ curl -X GET "http://localhost:6002/indexer/health"
| `size` | integer | N | 10 | 返回结果数量(1-100) |
| `from` | integer | N | 0 | 分页偏移量(用于分页) |
| `language` | string | N | "zh" | 返回语言:`zh`(中文)或 `en`(英文)。后端会根据此参数选择对应的中英文字段返回 |
-| `filters` | object | N | null | 精确匹配过滤器(见下文) |
-| `range_filters` | object | N | null | 数值范围过滤器(见下文) |
-| `facets` | array | N | null | 分面配置(见下文) |
+| `filters` | object | N | null | 精确匹配过滤器(见[过滤器详解](#33-过滤器详解)) |
+| `range_filters` | object | N | null | 数值范围过滤器(见[过滤器详解](#33-过滤器详解)) |
+| `facets` | array | N | null | 分面配置(见[分面配置](#34-分面配置)) |
| `sort_by` | string | N | null | 排序字段名。支持:`price`(价格)、`sales`(销量)、`create_time`(创建时间)、`update_time`(更新时间)。默认按相关性排序 |
| `sort_order` | string | N | "desc" | 排序方向:`asc`(升序)或 `desc`(降序)。注意:`price`+`asc`=价格从低到高,`price`+`desc`=价格从高到低(后端自动映射为min_price或max_price) |
| `min_score` | float | N | null | 最小相关性分数阈值 |
-| `sku_filter_dimension` | array[string] | N | null | 子SKU筛选维度列表(店铺配置)。指定后,每个SPU下的SKU将按这些维度的组合进行分组,每个组合只返回第一个SKU。支持的值:`option1`、`option2`、`option3` 或选项名称(如 `color`、`size`)。详见下文说明 |
+| `sku_filter_dimension` | array[string] | N | null | 子SKU筛选维度列表(见[SKU筛选维度](#35-sku筛选维度)) |
| `debug` | boolean | N | false | 是否返回调试信息 |
| `user_id` | string | N | null | 用户ID(用于个性化,预留) |
| `session_id` | string | N | null | 会话ID(用于分析,预留) |
-### 过滤器详解
+### 3.3 过滤器详解
-#### 1. 精确匹配过滤器 (filters)
+#### 3.3.1 精确匹配过滤器 (filters)
-用于精确匹配或多值匹配。对于普通字段,数组表示 OR 逻辑(匹配任意一个值);对于 specifications 字段,按维度分组处理(见下文)。
+用于精确匹配或多值匹配。对于普通字段,数组表示 OR 逻辑(匹配任意一个值);对于 specifications 字段,按维度分组处理。
**格式**:
```json
@@ -396,7 +268,7 @@ curl -X GET "http://localhost:6002/indexer/health"
- **不同维度**(不同的 `name`)之间是 **AND** 关系(求交集)
- **相同维度**(相同的 `name`)的多个值之间是 **OR** 关系(求并集)
-**常用过滤字段**:
+**常用过滤字段**(详见[常用字段列表](#83-常用字段列表)):
- `category_name`: 类目名称
- `category1_name`, `category2_name`, `category3_name`: 多级类目
- `category_id`: 类目ID
@@ -405,7 +277,7 @@ curl -X GET "http://localhost:6002/indexer/health"
- `option1_name`, `option2_name`, `option3_name`: 选项名称
- `specifications`: 规格过滤(嵌套字段,格式见上文)
-#### 2. 范围过滤器 (range_filters)
+#### 3.3.2 范围过滤器 (range_filters)
用于数值字段的范围过滤。
@@ -435,18 +307,18 @@ curl -X GET "http://localhost:6002/indexer/health"
**注意**: 至少需要指定一个操作符。
-**常用范围字段**:
+**常用范围字段**(详见[常用字段列表](#83-常用字段列表)):
- `min_price`: 最低价格
- `max_price`: 最高价格
- `compare_at_price`: 原价
- `create_time`: 创建时间
- `update_time`: 更新时间
-#### 3. 分面配置 (facets)
+### 3.4 分面配置
用于生成分面统计(分组聚合),常用于构建筛选器UI。
-**配置格式**(对象数组):
+#### 3.4.1 配置格式
```json
{
@@ -483,7 +355,7 @@ curl -X GET "http://localhost:6002/indexer/health"
}
```
-**Facet 字段说明**:
+#### 3.4.2 Facet 字段说明
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|------|------|------|--------|------|
@@ -493,22 +365,21 @@ curl -X GET "http://localhost:6002/indexer/health"
| `disjunctive` | bool | 否 | false | **是否支持多选模式**(见下文详细说明) |
| `ranges` | array | 否 | null | 范围配置(仅 `type="range"` 时需要) |
-#### 🆕 Multi-Select Faceting(多选分面)
+#### 3.4.3 Multi-Select Faceting(多选分面)
**重要特性**: `disjunctive` 字段控制分面的行为模式。
-
-##### 标准模式 (disjunctive: false)
+**标准模式 (disjunctive: false)**:
- **行为**: 选中某个分面值后,该分面只显示选中的值
- **适用场景**: 层级类目、互斥选择
- **示例**: 类目下钻(玩具 > 娃娃 > 芭比)
-##### Multi-Select 模式 (disjunctive: true) ⭐
+**Multi-Select 模式 (disjunctive: true)** ⭐:
- **行为**: 选中某个分面值后,该分面仍显示所有可选项
- **适用场景**: 颜色、品牌、尺码等可切换属性
- **示例**: 选择了"红色"后,仍能看到"蓝色"、"绿色"等选项
-##### 推荐配置
+**推荐配置**:
| 分面类型 | disjunctive | 原因 |
|---------|-------------|------|
@@ -518,7 +389,7 @@ curl -X GET "http://localhost:6002/indexer/health"
| 类目 | `false` | 层级下钻 |
| 价格区间 | `false` | 互斥选择 |
-**规格分面说明**:
+#### 3.4.4 规格分面说明
`specifications` 是嵌套字段,支持两种分面模式:
@@ -584,13 +455,7 @@ curl -X GET "http://localhost:6002/indexer/health"
}
```
-**分面配置参数**:
-- `field`: 字段名(必填)
-- `size`: 返回的分组数量(默认:10,范围:1-100)
-- `type`: 分面类型,`terms`(分组统计)或 `range`(范围统计)
-- `ranges`: 范围定义(仅当 type='range' 时需要)
-
-### SKU筛选维度 (sku_filter_dimension)
+### 3.5 SKU筛选维度
**功能说明**:
`sku_filter_dimension` 用于控制搜索列表页中 **每个 SPU 下方可切换的子款式(子 SKU)维度**,为字符串列表。
@@ -630,9 +495,7 @@ curl -X GET "http://localhost:6002/indexer/health"
}
```
----
-
-### 布尔表达式语法
+### 3.6 布尔表达式语法
搜索查询支持布尔表达式,提供更灵活的搜索能力。
@@ -662,63 +525,151 @@ curl -X GET "http://localhost:6002/indexer/health"
"玩具 AND (乐高 OR 芭比)" // 复杂查询
```
----
+### 3.7 搜索建议接口
-## 响应格式说明
+> ⚠️ **TODO**: 此接口当前为框架实现,功能暂未实现,仅返回空结果。接口和响应格式已经固定,可平滑扩展。
+
+- **端点**: `GET /search/suggestions`
+- **描述**: 返回搜索建议(自动补全/热词)。当前为框架实现,接口和响应格式已经固定,可平滑扩展。
+
+#### 查询参数
+
+| 参数 | 类型 | 必填 | 默认值 | 描述 |
+|------|------|------|--------|------|
+| `q` | string | Y | - | 查询字符串(至少 1 个字符) |
+| `size` | integer | N | 5 | 返回建议数量(1-20) |
+| `types` | string | N | `query` | 建议类型(逗号分隔):`query`, `product`, `category`, `brand` |
-### 标准响应结构
+#### 响应示例
```json
{
- "results": [
+ "query": "芭",
+ "suggestions": [
{
- "spu_id": "12345",
- "title": "芭比时尚娃娃",
- "brief": "高品质芭比娃娃",
- "description": "详细描述...",
- "vendor": "美泰",
- "category": "玩具",
- "category_path": "玩具/娃娃/时尚",
- "category_name": "时尚",
- "category_id": "cat_001",
- "category_level": 3,
- "category1_name": "玩具",
- "category2_name": "娃娃",
- "category3_name": "时尚",
- "tags": ["娃娃", "玩具", "女孩"],
- "price": 89.99,
- "compare_at_price": 129.99,
- "currency": "USD",
- "image_url": "https://example.com/image.jpg",
- "in_stock": true,
- "sku_prices": [89.99, 99.99, 109.99],
- "sku_weights": [100, 150, 200],
- "sku_weight_units": ["g", "g", "g"],
- "total_inventory": 500,
- "option1_name": "color",
- "option2_name": "size",
- "option3_name": null,
- "specifications": [
- {"sku_id": "sku_001", "name": "color", "value": "pink"},
- {"sku_id": "sku_001", "name": "size", "value": "standard"}
- ],
- "skus": [
- {
- "sku_id": "67890",
- "price": 89.99,
- "compare_at_price": 129.99,
- "sku": "BARBIE-001",
- "stock": 100,
- "weight": 0.1,
- "weight_unit": "kg",
- "option1_value": "pink",
- "option2_value": "standard",
- "option3_value": null,
- "image_src": "https://example.com/sku1.jpg"
- }
- ],
- "relevance_score": 8.5
- }
+ "text": "芭比娃娃",
+ "type": "query",
+ "highlight": "芭比娃娃",
+ "popularity": 850
+ }
+ ],
+ "took_ms": 5
+}
+```
+
+#### 请求示例
+
+```bash
+curl "http://localhost:6002/search/suggestions?q=芭&size=5&types=query,product"
+```
+
+### 3.8 即时搜索接口
+
+> ⚠️ **TODO**: 此接口当前为框架实现,功能暂未实现,调用标准搜索接口。后续需要优化即时搜索性能(添加防抖/节流、实现结果缓存、简化返回字段)。
+
+- **端点**: `GET /search/instant`
+- **描述**: 边输入边搜索,采用轻量参数响应当前输入。底层复用标准搜索能力。
+
+#### 查询参数
+
+| 参数 | 类型 | 必填 | 默认值 | 描述 |
+|------|------|------|--------|------|
+| `q` | string | Y | - | 搜索查询(至少 2 个字符) |
+| `size` | integer | N | 5 | 返回结果数量(1-20) |
+
+#### 请求示例
+
+```bash
+curl "http://localhost:6002/search/instant?q=玩具&size=5"
+```
+
+### 3.9 获取单个文档
+
+- **端点**: `GET /search/{doc_id}`
+- **描述**: 根据文档 ID 获取单个商品详情,用于点击结果后的详情页或排查问题。
+
+#### 路径参数
+
+| 参数 | 类型 | 描述 |
+|------|------|------|
+| `doc_id` | string | 商品或文档 ID |
+
+#### 响应示例
+
+```json
+{
+ "id": "12345",
+ "source": {
+ "title_zh": "芭比时尚娃娃",
+ "min_price": 89.99,
+ "category1_name": "玩具"
+ }
+}
+```
+
+#### 请求示例
+
+```bash
+curl "http://localhost:6002/search/12345"
+```
+
+---
+
+## 响应格式说明
+
+### 4.1 标准响应结构
+
+```json
+{
+ "results": [
+ {
+ "spu_id": "12345",
+ "title": "芭比时尚娃娃",
+ "brief": "高品质芭比娃娃",
+ "description": "详细描述...",
+ "vendor": "美泰",
+ "category": "玩具",
+ "category_path": "玩具/娃娃/时尚",
+ "category_name": "时尚",
+ "category_id": "cat_001",
+ "category_level": 3,
+ "category1_name": "玩具",
+ "category2_name": "娃娃",
+ "category3_name": "时尚",
+ "tags": ["娃娃", "玩具", "女孩"],
+ "price": 89.99,
+ "compare_at_price": 129.99,
+ "currency": "USD",
+ "image_url": "https://example.com/image.jpg",
+ "in_stock": true,
+ "sku_prices": [89.99, 99.99, 109.99],
+ "sku_weights": [100, 150, 200],
+ "sku_weight_units": ["g", "g", "g"],
+ "total_inventory": 500,
+ "option1_name": "color",
+ "option2_name": "size",
+ "option3_name": null,
+ "specifications": [
+ {"sku_id": "sku_001", "name": "color", "value": "pink"},
+ {"sku_id": "sku_001", "name": "size", "value": "standard"}
+ ],
+ "skus": [
+ {
+ "sku_id": "67890",
+ "price": 89.99,
+ "compare_at_price": 129.99,
+ "sku": "BARBIE-001",
+ "stock": 100,
+ "weight": 0.1,
+ "weight_unit": "kg",
+ "option1_value": "pink",
+ "option2_value": "standard",
+ "option3_value": null,
+ "image_src": "https://example.com/sku1.jpg"
+ }
+ ],
+ "relevance_score": 8.5
+ }
],
"total": 118,
"max_score": 8.5,
@@ -765,7 +716,7 @@ curl -X GET "http://localhost:6002/indexer/health"
}
```
-### 响应字段说明
+### 4.2 响应字段说明
| 字段 | 类型 | 说明 |
|------|------|------|
@@ -781,7 +732,7 @@ curl -X GET "http://localhost:6002/indexer/health"
| `query_info` | object | 查询处理信息 |
| `took_ms` | integer | 搜索耗时(毫秒) |
-### SpuResult字段说明
+### 4.3 SpuResult字段说明
| 字段 | 类型 | 说明 |
|------|------|------|
@@ -816,35 +767,255 @@ curl -X GET "http://localhost:6002/indexer/health"
| `skus` | array | SKU 列表 |
| `relevance_score` | float | 相关性分数 |
-**多语言字段说明**:
-- `title`, `brief`, `description`, `vendor`, `category_path`, `category_name` 会根据请求的 `language` 参数自动选择对应的中英文字段
-- `language="zh"`: 优先返回 `*_zh` 字段,如果为空则回退到 `*_en` 字段
-- `language="en"`: 优先返回 `*_en` 字段,如果为空则回退到 `*_zh` 字段
+### 4.4 SkuResult字段说明
+
+| 字段 | 类型 | 说明 |
+|------|------|------|
+| `sku_id` | string | SKU ID |
+| `price` | float | 价格 |
+| `compare_at_price` | float | 原价 |
+| `sku` | string | SKU编码(sku_code) |
+| `stock` | integer | 库存数量 |
+| `weight` | float | 重量 |
+| `weight_unit` | string | 重量单位 |
+| `option1_value` | string | 选项1取值(如color值) |
+| `option2_value` | string | 选项2取值(如size值) |
+| `option3_value` | string | 选项3取值 |
+| `image_src` | string | SKU图片地址 |
+
+### 4.5 多语言字段说明
+
+- `title`, `brief`, `description`, `vendor`, `category_path`, `category_name` 会根据请求的 `language` 参数自动选择对应的中英文字段
+- `language="zh"`: 优先返回 `*_zh` 字段,如果为空则回退到 `*_en` 字段
+- `language="en"`: 优先返回 `*_en` 字段,如果为空则回退到 `*_zh` 字段
+
+---
+
+## 索引接口
+
+### 5.1 全量索引接口
+
+- **端点**: `POST /indexer/bulk`
+- **描述**: 将指定租户的所有SPU数据导入到ES索引
+
+#### 请求参数
+
+```json
+{
+ "tenant_id": "162",
+ "recreate_index": false,
+ "batch_size": 500
+}
+```
+
+| 参数 | 类型 | 必填 | 默认值 | 说明 |
+|------|------|------|--------|------|
+| `tenant_id` | string | Y | - | 租户ID |
+| `recreate_index` | boolean | N | false | 是否重建索引(删除旧索引后创建新索引) |
+| `batch_size` | integer | N | 500 | 批量导入大小 |
+
+#### 响应格式
+
+**成功响应(200 OK)**:
+```json
+{
+ "success": true,
+ "total": 1000,
+ "indexed": 1000,
+ "failed": 0,
+ "elapsed_time": 12.34,
+ "index_name": "search_products",
+ "tenant_id": "162"
+}
+```
+
+**错误响应**:
+- `400 Bad Request`: 参数错误
+- `503 Service Unavailable`: 服务未初始化
+
+#### 请求示例
+
+**首次索引(重建索引)**:
+```bash
+curl -X POST "http://localhost:6002/indexer/bulk" \
+ -H "Content-Type: application/json" \
+ -d '{
+ "tenant_id": "162",
+ "recreate_index": true,
+ "batch_size": 500
+ }'
+```
+
+**查看日志**:
+```bash
+# 查看API日志(包含索引操作日志)
+tail -f logs/api.log
+
+# 或者查看所有日志文件
+tail -f logs/*.log
+```
+
+**增量更新(不重建索引)**:
+```bash
+curl -X POST "http://localhost:6002/indexer/bulk" \
+ -H "Content-Type: application/json" \
+ -d '{
+ "tenant_id": "162",
+ "recreate_index": false,
+ "batch_size": 500
+ }'
+```
+
+### 5.2 SPU索引接口
+
+- **端点**: `POST /indexer/spus`
+- **描述**: 获取SPU的ES文档数据(支持单个或批量)
+
+#### 请求参数
+
+```json
+{
+ "tenant_id": "162",
+ "spu_ids": ["123", "456", "789"]
+}
+```
+
+| 参数 | 类型 | 必填 | 说明 |
+|------|------|------|------|
+| `tenant_id` | string | Y | 租户ID |
+| `spu_ids` | array[string] | Y | SPU ID列表(1-100个) |
+
+#### 响应格式
+
+```json
+{
+ "success": [
+ {
+ "spu_id": "123",
+ "document": {
+ "tenant_id": "162",
+ "spu_id": "123",
+ "title_zh": "商品标题",
+ ...
+ }
+ },
+ {
+ "spu_id": "456",
+ "document": {...}
+ }
+ ],
+ "failed": [
+ {
+ "spu_id": "789",
+ "error": "SPU not found or deleted"
+ }
+ ],
+ "total": 3,
+ "success_count": 2,
+ "failed_count": 1
+}
+```
+
+#### 请求示例
+
+**单个SPU**:
+```bash
+curl -X POST "http://localhost:6002/indexer/spus" \
+ -H "Content-Type: application/json" \
+ -d '{
+ "tenant_id": "162",
+ "spu_ids": ["123"]
+ }'
+```
+
+**批量SPU**:
+```bash
+curl -X POST "http://localhost:6002/indexer/spus" \
+ -H "Content-Type: application/json" \
+ -d '{
+ "tenant_id": "162",
+ "spu_ids": ["123", "456", "789"]
+ }'
+```
+
+### 5.3 索引健康检查接口
+
+- **端点**: `GET /indexer/health`
+- **描述**: 检查索引服务的健康状态
+
+#### 响应格式
+
+```json
+{
+ "status": "available",
+ "database": "connected",
+ "preloaded_data": {
+ "category_mappings": 150
+ }
+}
+```
+
+#### 请求示例
+
+```bash
+curl -X GET "http://localhost:6002/indexer/health"
+```
+
+---
+
+## 管理接口
+
+### 6.1 健康检查
+
+- **端点**: `GET /admin/health`
+- **描述**: 检查服务与依赖(如 Elasticsearch)状态。
+
+```json
+{
+ "status": "healthy",
+ "elasticsearch": "connected",
+ "tenant_id": "tenant1"
+}
+```
+
+### 6.2 获取配置
+
+- **端点**: `GET /admin/config`
+- **描述**: 返回当前租户的脱敏配置,便于核对索引及排序表达式。
+
+```json
+{
+ "tenant_id": "tenant1",
+ "tenant_name": "Tenant1 Test Instance",
+ "es_index_name": "search_tenant1",
+ "num_fields": 20,
+ "num_indexes": 4,
+ "supported_languages": ["zh", "en", "ru"],
+ "ranking_expression": "bm25() + 0.2*text_embedding_relevance()",
+ "spu_enabled": false
+}
+```
+
+### 6.3 索引统计
-### SkuResult字段说明
+- **端点**: `GET /admin/stats`
+- **描述**: 获取索引文档数量与磁盘大小,方便监控。
-| 字段 | 类型 | 说明 |
-|------|------|------|
-| `sku_id` | string | SKU ID |
-| `price` | float | 价格 |
-| `compare_at_price` | float | 原价 |
-| `sku` | string | SKU编码(sku_code) |
-| `stock` | integer | 库存数量 |
-| `weight` | float | 重量 |
-| `weight_unit` | string | 重量单位 |
-| `option1_value` | string | 选项1取值(如color值) |
-| `option2_value` | string | 选项2取值(如size值) |
-| `option3_value` | string | 选项3取值 |
-| `image_src` | string | SKU图片地址 |
+```json
+{
+ "index_name": "search_tenant1",
+ "document_count": 10000,
+ "size_mb": 523.45
+}
+```
---
## 常见场景示例
-### 场景1:商品列表页搜索
-
-**需求**: 搜索"玩具",按价格从低到高排序,显示前20个结果
+### 7.1 基础搜索与排序
+**按价格从低到高排序**:
```json
{
"query": "玩具",
@@ -855,8 +1026,7 @@ curl -X GET "http://localhost:6002/indexer/health"
}
```
-**需求**: 搜索"玩具",按价格从高到低排序
-
+**按价格从高到低排序**:
```json
{
"query": "玩具",
@@ -867,8 +1037,7 @@ curl -X GET "http://localhost:6002/indexer/health"
}
```
-**需求**: 搜索"玩具",按销量从高到低排序
-
+**按销量从高到低排序**:
```json
{
"query": "玩具",
@@ -879,8 +1048,7 @@ curl -X GET "http://localhost:6002/indexer/health"
}
```
-**需求**: 搜索"玩具",按默认(相关性)排序
-
+**按默认(相关性)排序**:
```json
{
"query": "玩具",
@@ -889,34 +1057,36 @@ curl -X GET "http://localhost:6002/indexer/health"
}
```
-### 场景2:SKU筛选(按维度过滤)
+### 7.2 过滤搜索
-**需求**: 搜索"芭比娃娃",每个SPU下按颜色筛选,每种颜色只显示一个SKU
+**需求**: 搜索"玩具",筛选类目为"益智玩具",价格在50-200之间
```json
{
- "query": "芭比娃娃",
+ "query": "玩具",
"size": 20,
- "sku_filter_dimension": "color"
+ "language": "zh",
+ "filters": {
+ "category_name": "益智玩具"
+ },
+ "range_filters": {
+ "min_price": {
+ "gte": 50,
+ "lte": 200
+ }
+ }
}
```
-**说明**:
-- 如果 `option1_name` 为 `"color"`,则使用 `sku_filter_dimension: "color"` 可以按颜色分组
-- 每个SPU下,每种颜色只会返回第一个SKU
-- 如果维度不匹配,返回所有SKU(不进行过滤)
-
-### 场景3:带筛选的商品搜索
-
-**需求**: 搜索"玩具",筛选类目为"益智玩具",价格在50-200之间
+**需求**: 搜索"手机",筛选多个品牌,价格范围
```json
{
- "query": "玩具",
+ "query": "手机",
"size": 20,
"language": "zh",
"filters": {
- "category_name": "益智玩具"
+ "vendor_zh.keyword": ["品牌A", "品牌B"]
},
"range_filters": {
"min_price": {
@@ -927,7 +1097,7 @@ curl -X GET "http://localhost:6002/indexer/health"
}
```
-### 场景4:带分面的商品搜索
+### 7.3 分面搜索
**需求**: 搜索"玩具",获取类目和规格的分面统计,用于构建筛选器
@@ -944,31 +1114,15 @@ curl -X GET "http://localhost:6002/indexer/health"
}
```
-### 场景5:多条件组合搜索
-
-**需求**: 搜索"手机",筛选多个品牌,价格范围,并获取分面统计
+**需求**: 搜索"手机",获取价格区间和规格的分面统计
```json
{
"query": "手机",
"size": 20,
"language": "zh",
- "filters": {
- "vendor_zh.keyword": ["品牌A", "品牌B"]
- },
- "range_filters": {
- "min_price": {
- "gte": 50,
- "lte": 200
- }
- },
"facets": [
{
- "field": "category1_name",
- "size": 15,
- "type": "terms"
- },
- {
"field": "min_price",
"type": "range",
"ranges": [
@@ -983,13 +1137,11 @@ curl -X GET "http://localhost:6002/indexer/health"
"size": 10,
"type": "terms"
}
- ],
- "sort_by": "min_price",
- "sort_order": "asc"
+ ]
}
```
-### 场景6:规格过滤搜索
+### 7.4 规格过滤与分面
**需求**: 搜索"手机",筛选color为"white"的商品
@@ -1007,8 +1159,6 @@ curl -X GET "http://localhost:6002/indexer/health"
}
```
-### 场景7:多个规格过滤(不同维度AND,相同维度OR)
-
**需求**: 搜索"手机",筛选color为"white"且size为"256GB"的商品
```json
@@ -1043,8 +1193,6 @@ curl -X GET "http://localhost:6002/indexer/health"
}
```
-### 场景8:规格分面搜索
-
**需求**: 搜索"手机",获取所有规格的分面统计
```json
@@ -1072,8 +1220,6 @@ curl -X GET "http://localhost:6002/indexer/health"
}
```
-### 场景9:组合过滤和分面
-
**需求**: 搜索"手机",筛选类目和规格,并获取对应的分面统计
```json
@@ -1097,172 +1243,43 @@ curl -X GET "http://localhost:6002/indexer/health"
}
```
-### 场景10:布尔表达式搜索
-
-**需求**: 搜索包含"手机"和"智能"的商品,排除"二手"
-
-```json
-{
- "query": "手机 AND 智能 ANDNOT 二手",
- "size": 20
-}
-```
-
-### 场景11:分页查询
+### 7.5 SKU筛选
-**需求**: 获取第2页结果(每页20条)
+**需求**: 搜索"芭比娃娃",每个SPU下按颜色筛选,每种颜色只显示一个SKU
```json
{
- "query": "手机",
+ "query": "芭比娃娃",
"size": 20,
- "from": 20
-}
-```
-
----
-
----
-
-## 其他接口
-
-### 搜索建议(框架)
-
-- **端点**: `GET /search/suggestions`
-- **描述**: 返回搜索建议(自动补全/热词)。当前为框架实现,接口和响应格式已经固定,可平滑扩展。
-
-#### 查询参数
-
-| 参数 | 类型 | 必填 | 默认值 | 描述 |
-|------|------|------|--------|------|
-| `q` | string | Y | - | 查询字符串(至少 1 个字符) |
-| `size` | integer | N | 5 | 返回建议数量(1-20) |
-| `types` | string | N | `query` | 建议类型(逗号分隔):`query`, `product`, `category`, `brand` |
-
-#### 响应示例
-
-```json
-{
- "query": "芭",
- "suggestions": [
- {
- "text": "芭比娃娃",
- "type": "query",
- "highlight": "芭比娃娃",
- "popularity": 850
- }
- ],
- "took_ms": 5
-}
-```
-
-#### 请求示例
-
-```bash
-curl "http://localhost:6002/search/suggestions?q=芭&size=5&types=query,product"
-```
-
----
-
-### 即时搜索(框架)
-
-- **端点**: `GET /search/instant`
-- **描述**: 边输入边搜索,采用轻量参数响应当前输入。底层复用标准搜索能力。
-
-#### 查询参数
-
-| 参数 | 类型 | 必填 | 默认值 | 描述 |
-|------|------|------|--------|------|
-| `q` | string | Y | - | 搜索查询(至少 2 个字符) |
-| `size` | integer | N | 5 | 返回结果数量(1-20) |
-
-#### 请求示例
-
-```bash
-curl "http://localhost:6002/search/instant?q=玩具&size=5"
-```
-
----
-
-### 获取单个文档
-
-- **端点**: `GET /search/{doc_id}`
-- **描述**: 根据文档 ID 获取单个商品详情,用于点击结果后的详情页或排查问题。
-
-#### 路径参数
-
-| 参数 | 类型 | 描述 |
-|------|------|------|
-| `doc_id` | string | 商品或文档 ID |
-
-#### 响应示例
-
-```json
-{
- "id": "12345",
- "source": {
- "title_zh": "芭比时尚娃娃",
- "min_price": 89.99,
- "category1_name": "玩具"
- }
-}
-```
-
-#### 请求示例
-
-```bash
-curl "http://localhost:6002/search/12345"
-```
-
----
-
-## 管理接口
-
-### 健康检查
-
-- **端点**: `GET /admin/health`
-- **描述**: 检查服务与依赖(如 Elasticsearch)状态。
-
-```json
-{
- "status": "healthy",
- "elasticsearch": "connected",
- "tenant_id": "tenant1"
+ "sku_filter_dimension": ["color"]
}
```
----
+**说明**:
+- 如果 `option1_name` 为 `"color"`,则使用 `sku_filter_dimension: ["color"]` 可以按颜色分组
+- 每个SPU下,每种颜色只会返回第一个SKU
+- 如果维度不匹配,返回所有SKU(不进行过滤)
-### 获取配置
+### 7.6 布尔表达式搜索
-- **端点**: `GET /admin/config`
-- **描述**: 返回当前租户的脱敏配置,便于核对索引及排序表达式。
+**需求**: 搜索包含"手机"和"智能"的商品,排除"二手"
```json
{
- "tenant_id": "tenant1",
- "tenant_name": "Tenant1 Test Instance",
- "es_index_name": "search_tenant1",
- "num_fields": 20,
- "num_indexes": 4,
- "supported_languages": ["zh", "en", "ru"],
- "ranking_expression": "bm25() + 0.2*text_embedding_relevance()",
- "spu_enabled": false
+ "query": "手机 AND 智能 ANDNOT 二手",
+ "size": 20
}
```
----
-
-### 索引统计
+### 7.7 分页查询
-- **端点**: `GET /admin/stats`
-- **描述**: 获取索引文档数量与磁盘大小,方便监控。
+**需求**: 获取第2页结果(每页20条)
```json
{
- "index_name": "search_tenant1",
- "document_count": 10000,
- "size_mb": 523.45
+ "query": "手机",
+ "size": 20,
+ "from": 20
}
```
@@ -1270,7 +1287,7 @@ curl "http://localhost:6002/search/12345"
## 数据模型
-### 商品字段
+### 8.1 商品字段定义
| 字段名 | 类型 | 描述 |
|--------|------|------|
@@ -1303,11 +1320,20 @@ curl "http://localhost:6002/search/12345"
> 所有租户共享统一的索引结构。文本字段支持中英文双语,后端根据 `language` 参数自动选择对应字段返回。
----
+### 8.2 字段类型速查
-## 附录
+| 类型 | ES Mapping | 用途 |
+|------|------------|------|
+| `text` | `text` | 全文检索(支持中英文分析器) |
+| `keyword` | `keyword` | 精确匹配、聚合、排序 |
+| `integer` | `integer` | 整数 |
+| `long` | `long` | 长整数 |
+| `float` | `float` | 浮点数 |
+| `date` | `date` | 日期时间 |
+| `nested` | `nested` | 嵌套对象(specifications, skus, image_embedding) |
+| `dense_vector` | `dense_vector` | 向量字段(title_embedding,仅用于搜索) |
-### 常用字段列表
+### 8.3 常用字段列表
#### 过滤字段
@@ -1317,6 +1343,7 @@ curl "http://localhost:6002/search/12345"
- `vendor_zh.keyword`, `vendor_en.keyword`: 供应商/品牌(使用keyword子字段)
- `tags`: 标签(keyword类型)
- `option1_name`, `option2_name`, `option3_name`: 选项名称
+- `specifications`: 规格过滤(嵌套字段,格式见[过滤器详解](#33-过滤器详解))
#### 范围字段
@@ -1338,26 +1365,13 @@ curl "http://localhost:6002/search/12345"
- `sort_by: "price"` + `sort_order: "asc"` → 按 `min_price` 升序(价格从低到高)
- `sort_by: "price"` + `sort_order: "desc"` → 按 `max_price` 降序(价格从高到低)
-### 支持的分析器
+### 8.4 支持的分析器
| 分析器 | 语言 | 描述 |
|--------|------|------|
| `index_ansj` | 中文 | 中文索引分析器(用于中文字段) |
| `query_ansj` | 中文 | 中文查询分析器(用于中文字段) |
-| `hanlp_index`(暂不支持) | 中文 | 中文索引分析器(用于中文字段) |
-| `hanlp_standard`(暂不支持) | 中文 | 中文查询分析器(用于中文字段) |
+| `hanlp_index` ⚠️ TODO(暂不支持) | 中文 | 中文索引分析器(用于中文字段) |
+| `hanlp_standard` ⚠️ TODO(暂不支持) | 中文 | 中文查询分析器(用于中文字段) |
| `english` | 英文 | 标准英文分析器(用于英文字段) |
| `lowercase` | - | 小写标准化器(用于keyword子字段) |
-
-### 字段类型速查
-
-| 类型 | ES Mapping | 用途 |
-|------|------------|------|
-| `text` | `text` | 全文检索(支持中英文分析器) |
-| `keyword` | `keyword` | 精确匹配、聚合、排序 |
-| `integer` | `integer` | 整数 |
-| `long` | `long` | 长整数 |
-| `float` | `float` | 浮点数 |
-| `date` | `date` | 日期时间 |
-| `nested` | `nested` | 嵌套对象(specifications, skus, image_embedding) |
-| `dense_vector` | `dense_vector` | 向量字段(title_embedding,仅用于搜索) |
--
libgit2 0.21.2