From 11237cf2218f281a55e60066a28c1f035f33ef7f Mon Sep 17 00:00:00 2001 From: tangwang Date: Mon, 8 Dec 2025 10:06:43 +0800 Subject: [PATCH] 搜索API对接指南.md --- docs/搜索API对接指南.md | 1038 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 1 file changed, 526 insertions(+), 512 deletions(-) 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