# 搜索API接口对接指南 本文档为搜索服务的使用方提供完整的API对接指南,包括接口说明、请求参数、响应格式和使用示例。 ## 目录 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. [响应格式说明](#响应格式说明) - 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 - **数据格式**: JSON - **字符编码**: UTF-8 - **请求方法**: POST(搜索接口) **重要提示**: `tenant_id` 通过 HTTP Header `X-Tenant-ID` 传递,不在请求体中。 ### 1.2 最简单的搜索请求 ```bash curl -X POST "http://120.76.41.98:6002/search/" \ -H "Content-Type: application/json" \ -H "X-Tenant-ID: 162" \ -d '{"query": "芭比娃娃"}' ``` ### 1.3 带过滤与分页的搜索 ```bash curl -X POST "http://120.76.41.98:6002/search/" \ -H "Content-Type: application/json" \ -H "X-Tenant-ID: 162" \ -d '{ "query": "芭比娃娃", "size": 5, "from": 10, "range_filters": { "min_price": { "gte": 50, "lte": 200 }, "create_time": { "gte": "2020-01-01T00:00:00Z" } }, "sort_by": "price", "sort_order": "asc" }' ``` ### 1.4 开启分面的搜索 ```bash curl -X POST "http://120.76.41.98:6002/search/" \ -H "Content-Type: application/json" \ -H "X-Tenant-ID: 162" \ -d '{ "query": "芭比娃娃", "facets": [ {"field": "category1_name", "size": 10, "type": "terms"}, {"field": "specifications.color", "size": 10, "type": "terms"}, {"field": "specifications.size", "size": 10, "type": "terms"} ], "min_score": 0.2 }' ``` --- ## 接口概览 | 接口 | 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 | `/admin/health` | 服务健康检查 | | 获取配置 | GET | `/admin/config` | 获取租户配置 | | 索引统计 | GET | `/admin/stats` | 获取索引统计信息 | --- ## 搜索接口 ### 3.1 接口信息 - **端点**: `POST /search/` - **描述**: 执行文本搜索查询,支持多语言、布尔表达式、过滤器和分面搜索 ### 3.2 请求参数 #### 完整请求体结构 ```json { "query": "string (required)", "size": 10, "from": 0, "language": "zh", "filters": {}, "range_filters": {}, "facets": [], "sort_by": "string", "sort_order": "desc", "min_score": 0.0, "sku_filter_dimension": ["string"], "debug": false, "user_id": "string", "session_id": "string" } ``` #### 参数详细说明 | 参数 | 类型 | 必填 | 默认值 | 说明 | |------|------|------|--------|------| | `query` | string | Y | - | 搜索查询字符串,支持布尔表达式(AND, OR, RANK, ANDNOT) | | `size` | integer | N | 10 | 返回结果数量(1-100) | | `from` | integer | N | 0 | 分页偏移量(用于分页) | | `language` | string | N | "zh" | 返回语言:`zh`(中文)或 `en`(英文)。后端会根据此参数选择对应的中英文字段返回 | | `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筛选维度列表(见[SKU筛选维度](#35-sku筛选维度)) | | `debug` | boolean | N | false | 是否返回调试信息 | | `user_id` | string | N | null | 用户ID(用于个性化,预留) | | `session_id` | string | N | null | 会话ID(用于分析,预留) | ### 3.3 过滤器详解 #### 3.3.1 精确匹配过滤器 (filters) 用于精确匹配或多值匹配。对于普通字段,数组表示 OR 逻辑(匹配任意一个值);对于 specifications 字段,按维度分组处理。 **格式**: ```json { "filters": { "category_name": "手机", // 可以为单值 或者 数组 匹配数组中任意一个 "category1_name": "服装", // 可以为单值 或者 数组 匹配数组中任意一个 "category2_name": "男装", // 可以为单值 或者 数组 匹配数组中任意一个 "category3_name": "衬衫", // 可以为单值 或者 数组 匹配数组中任意一个 "vendor_zh.keyword": ["奇乐", "品牌A"], // 可以为单值 或者 数组 匹配数组中任意一个 "tags": "手机", // 可以为单值 或者 数组 匹配数组中任意一个 // specifications 嵌套过滤(特殊格式) "specifications": { "name": "color", "value": "white" } } } ``` **支持的值类型**: - 字符串:精确匹配 - 整数:精确匹配 - 布尔值:精确匹配 - 数组:匹配任意值(OR 逻辑) - 对象:specifications 嵌套过滤(见下文) **Specifications 嵌套过滤**: `specifications` 是嵌套字段,支持按规格名称和值进行过滤。 **单个规格过滤**: ```json { "filters": { "specifications": { "name": "color", "value": "white" } } } ``` 查询规格名称为"color"且值为"white"的商品。 **多个规格过滤(按维度分组)**: ```json { "filters": { "specifications": [ {"name": "color", "value": "white"}, {"name": "size", "value": "256GB"} ] } } ``` 查询同时满足所有规格的商品(color=white **且** size=256GB)。 **相同维度的多个值(OR 逻辑)**: ```json { "filters": { "specifications": [ {"name": "size", "value": "3"}, {"name": "size", "value": "4"}, {"name": "size", "value": "5"}, {"name": "color", "value": "green"} ] } } ``` 查询满足 (size=3 **或** size=4 **或** size=5) **且** color=green 的商品。 **过滤逻辑说明**: - **不同维度**(不同的 `name`)之间是 **AND** 关系(求交集) - **相同维度**(相同的 `name`)的多个值之间是 **OR** 关系(求并集) **常用过滤字段**(详见[常用字段列表](#83-常用字段列表)): - `category_name`: 类目名称 - `category1_name`, `category2_name`, `category3_name`: 多级类目 - `category_id`: 类目ID - `vendor_zh.keyword`, `vendor_en.keyword`: 供应商/品牌(使用keyword子字段) - `tags`: 标签(keyword类型,支持数组) - `option1_name`, `option2_name`, `option3_name`: 选项名称 - `specifications`: 规格过滤(嵌套字段,格式见上文) #### 3.3.2 范围过滤器 (range_filters) 用于数值字段的范围过滤。 **格式**: ```json { "range_filters": { "min_price": { "gte": 50, // 大于等于 "lte": 200 // 小于等于 }, "max_price": { "gt": 100 // 大于 }, "create_time": { "gte": "2024-01-01T00:00:00Z" // 日期时间字符串 } } } ``` **支持的操作符**: - `gte`: 大于等于 (>=) - `gt`: 大于 (>) - `lte`: 小于等于 (<=) - `lt`: 小于 (<) **注意**: 至少需要指定一个操作符。 **常用范围字段**(详见[常用字段列表](#83-常用字段列表)): - `min_price`: 最低价格 - `max_price`: 最高价格 - `compare_at_price`: 原价 - `create_time`: 创建时间 - `update_time`: 更新时间 ### 3.4 分面配置 用于生成分面统计(分组聚合),常用于构建筛选器UI。 #### 3.4.1 配置格式 ```json { "facets": [ { "field": "category1_name", "size": 15, "type": "terms", "disjunctive": false }, { "field": "brand_name", "size": 10, "type": "terms", "disjunctive": true }, { "field": "specifications.color", "size": 20, "type": "terms", "disjunctive": true }, { "field": "min_price", "type": "range", "ranges": [ {"key": "0-50", "to": 50}, {"key": "50-100", "from": 50, "to": 100}, {"key": "100-200", "from": 100, "to": 200}, {"key": "200+", "from": 200} ] } ] } ``` #### 3.4.2 Facet 字段说明 | 字段 | 类型 | 必填 | 默认值 | 说明 | |------|------|------|--------|------| | `field` | string | 是 | - | 分面字段名 | | `size` | int | 否 | 10 | 返回的分面值数量(1-100) | | `type` | string | 否 | "terms" | 分面类型:`terms`(词条聚合)或 `range`(范围聚合) | | `disjunctive` | bool | 否 | false | **是否支持多选模式**(见下文详细说明) | | `ranges` | array | 否 | null | 范围配置(仅 `type="range"` 时需要) | #### 3.4.3 Multi-Select Faceting(多选分面) **重要特性**: `disjunctive` 字段控制分面的行为模式。 **标准模式 (disjunctive: false)**: - **行为**: 选中某个分面值后,该分面只显示选中的值 - **适用场景**: 层级类目、互斥选择 - **示例**: 类目下钻(玩具 > 娃娃 > 芭比) **Multi-Select 模式 (disjunctive: true)** ⭐: - **行为**: 选中某个分面值后,该分面仍显示所有可选项 - **适用场景**: 颜色、品牌、尺码等可切换属性 - **示例**: 选择了"红色"后,仍能看到"蓝色"、"绿色"等选项 **推荐配置**: | 分面类型 | disjunctive | 原因 | |---------|-------------|------| | 颜色 | `true` | 用户需要切换颜色 | | 品牌 | `true` | 用户需要比较品牌 | | 尺码 | `true` | 用户需要查看其他尺码 | | 类目 | `false` | 层级下钻 | | 价格区间 | `false` | 互斥选择 | #### 3.4.4 规格分面说明 `specifications` 是嵌套字段,支持两种分面模式: **模式1:所有规格名称的分面**: ```json { "facets": [ { "field": "specifications", "size": 10, "type": "terms" } ] } ``` 返回所有规格名称(name)及其对应的值(value)列表。每个 name 会生成一个独立的分面结果。 **模式2:指定规格名称的分面**: ```json { "facets": [ { "field": "specifications.color", "size": 20, "type": "terms", "disjunctive": true }, { "field": "specifications.size", "size": 15, "type": "terms", "disjunctive": true } ] } ``` 只返回指定规格名称的值列表。格式:`specifications.{name}`,其中 `{name}` 是规格名称(如"color"、"size"、"material")。 **返回格式示例**: ```json { "facets": [ { "field": "specifications.color", "label": "color", "type": "terms", "values": [ {"value": "white", "count": 50, "selected": true}, // ✓ selected 字段由后端标记 {"value": "black", "count": 30, "selected": false}, {"value": "red", "count": 20, "selected": false} ] }, { "field": "specifications.size", "label": "size", "type": "terms", "values": [ {"value": "256GB", "count": 40, "selected": false}, {"value": "512GB", "count": 20, "selected": false} ] } ] } ``` ### 3.5 SKU筛选维度 **功能说明**: `sku_filter_dimension` 用于控制搜索列表页中 **每个 SPU 下方可切换的子款式(子 SKU)维度**,为字符串列表。 在店铺的 **主题装修配置** 中,商家可以为店铺设置一个或多个子款式筛选维度(例如 `color`、`size`),前端列表页会在每个 SPU 下展示这些维度对应的子 SKU 列表,用户可以通过点击不同维度值(如不同颜色)来切换展示的子款式。 当指定 `sku_filter_dimension` 后,后端会根据店铺的这项配置,从所有 SKU 中筛选出这些维度组合对应的子 SKU 数据:系统会按指定维度**组合**对 SKU 进行分组,每个维度组合只返回第一个 SKU(从简实现,选择该组合下的第一款),其余不在这些维度组合中的子 SKU 将不返回。 **支持的维度值**: 1. **直接选项字段**: `option1`、`option2`、`option3` - 直接使用对应的 `option1_value`、`option2_value`、`option3_value` 字段进行分组 2. **规格/选项名称**: 通过 `option1_name`、`option2_name`、`option3_name` 匹配 - 例如:如果 `option1_name` 为 `"color"`,则可以使用 `sku_filter_dimension: ["color"]` 来按颜色分组 **示例**: **按颜色筛选(假设 option1_name = "color")**: ```json { "query": "芭比娃娃", "sku_filter_dimension": ["color"] } ``` **按选项1筛选**: ```json { "query": "芭比娃娃", "sku_filter_dimension": ["option1"] } ``` **按颜色 + 尺寸组合筛选(假设 option1_name = "color", option2_name = "size")**: ```json { "query": "芭比娃娃", "sku_filter_dimension": ["color", "size"] } ``` ### 3.6 布尔表达式语法 搜索查询支持布尔表达式,提供更灵活的搜索能力。 **支持的操作符**: | 操作符 | 描述 | 示例 | |--------|------|------| | `AND` | 所有词必须匹配 | `玩具 AND 乐高` | | `OR` | 任意词匹配 | `芭比 OR 娃娃` | | `ANDNOT` | 排除特定词 | `玩具 ANDNOT 电动` | | `RANK` | 排序加权(不强制匹配) | `玩具 RANK 乐高` | | `()` | 分组 | `玩具 AND (乐高 OR 芭比)` | **操作符优先级**(从高到低): 1. `()` - 括号 2. `ANDNOT` - 排除 3. `AND` - 与 4. `OR` - 或 5. `RANK` - 排序 **示例**: ``` "芭比娃娃" // 简单查询 "玩具 AND 乐高" // AND 查询 "芭比 OR 娃娃" // OR 查询 "玩具 ANDNOT 电动" // 排除查询 "玩具 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 { "query": "芭", "suggestions": [ { "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, "facets": [ { "field": "category1_name", "label": "category1_name", "type": "terms", "values": [ { "value": "玩具", "label": "玩具", "count": 85, "selected": false } ] }, { "field": "specifications.color", "label": "color", "type": "terms", "values": [ { "value": "pink", "label": "pink", "count": 30, "selected": false } ] } ], "query_info": { "original_query": "芭比娃娃", "detected_language": "zh", "translations": { "en": "barbie doll" } }, "suggestions": [], "related_searches": [], "took_ms": 45, "performance_info": null, "debug_info": null } ``` ### 4.2 响应字段说明 | 字段 | 类型 | 说明 | |------|------|------| | `results` | array | 搜索结果列表(SpuResult对象数组) | | `results[].spu_id` | string | SPU ID | | `results[].title` | string | 商品标题 | | `results[].price` | float | 价格(min_price) | | `results[].skus` | array | SKU列表(如果指定了`sku_filter_dimension`,则按维度过滤后的SKU) | | `results[].relevance_score` | float | 相关性分数 | | `total` | integer | 匹配的总文档数 | | `max_score` | float | 最高相关性分数 | | `facets` | array | 分面统计结果 | | `query_info` | object | 查询处理信息 | | `took_ms` | integer | 搜索耗时(毫秒) | ### 4.3 SpuResult字段说明 | 字段 | 类型 | 说明 | |------|------|------| | `spu_id` | string | SPU ID | | `title` | string | 商品标题(根据language参数自动选择title_zh或title_en) | | `brief` | string | 商品短描述(根据language参数自动选择) | | `description` | string | 商品详细描述(根据language参数自动选择) | | `vendor` | string | 供应商/品牌(根据language参数自动选择) | | `category` | string | 类目(兼容字段,等同于category_name) | | `category_path` | string | 类目路径(多级,用于面包屑,根据language参数自动选择) | | `category_name` | string | 类目名称(展示用,根据language参数自动选择) | | `category_id` | string | 类目ID | | `category_level` | integer | 类目层级(1/2/3) | | `category1_name` | string | 一级类目名称 | | `category2_name` | string | 二级类目名称 | | `category3_name` | string | 三级类目名称 | | `tags` | array[string] | 标签列表 | | `price` | float | 价格(min_price) | | `compare_at_price` | float | 原价 | | `currency` | string | 货币单位(默认USD) | | `image_url` | string | 主图URL | | `in_stock` | boolean | 是否有库存(任意SKU有库存即为true) | | `sku_prices` | array[float] | 所有SKU价格列表 | | `sku_weights` | array[integer] | 所有SKU重量列表 | | `sku_weight_units` | array[string] | 所有SKU重量单位列表 | | `total_inventory` | integer | 总库存 | | `sales` | integer | 销量(展示销量) | | `option1_name` | string | 选项1名称(如"color") | | `option2_name` | string | 选项2名称(如"size") | | `option3_name` | string | 选项3名称 | | `specifications` | array[object] | 规格列表(与ES specifications字段对应) | | `skus` | array | SKU 列表 | | `relevance_score` | float | 相关性分数 | ### 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 索引统计 - **端点**: `GET /admin/stats` - **描述**: 获取索引文档数量与磁盘大小,方便监控。 ```json { "index_name": "search_tenant1", "document_count": 10000, "size_mb": 523.45 } ``` --- ## 常见场景示例 ### 7.1 基础搜索与排序 **按价格从低到高排序**: ```json { "query": "玩具", "size": 20, "from": 0, "sort_by": "price", "sort_order": "asc" } ``` **按价格从高到低排序**: ```json { "query": "玩具", "size": 20, "from": 0, "sort_by": "price", "sort_order": "desc" } ``` **按销量从高到低排序**: ```json { "query": "玩具", "size": 20, "from": 0, "sort_by": "sales", "sort_order": "desc" } ``` **按默认(相关性)排序**: ```json { "query": "玩具", "size": 20, "from": 0 } ``` ### 7.2 过滤搜索 **需求**: 搜索"玩具",筛选类目为"益智玩具",价格在50-200之间 ```json { "query": "玩具", "size": 20, "language": "zh", "filters": { "category_name": "益智玩具" }, "range_filters": { "min_price": { "gte": 50, "lte": 200 } } } ``` **需求**: 搜索"手机",筛选多个品牌,价格范围 ```json { "query": "手机", "size": 20, "language": "zh", "filters": { "vendor_zh.keyword": ["品牌A", "品牌B"] }, "range_filters": { "min_price": { "gte": 50, "lte": 200 } } } ``` ### 7.3 分面搜索 **需求**: 搜索"玩具",获取类目和规格的分面统计,用于构建筛选器 ```json { "query": "玩具", "size": 20, "language": "zh", "facets": [ {"field": "category1_name", "size": 15, "type": "terms"}, {"field": "category2_name", "size": 10, "type": "terms"}, {"field": "specifications", "size": 10, "type": "terms"} ] } ``` **需求**: 搜索"手机",获取价格区间和规格的分面统计 ```json { "query": "手机", "size": 20, "language": "zh", "facets": [ { "field": "min_price", "type": "range", "ranges": [ {"key": "0-50", "to": 50}, {"key": "50-100", "from": 50, "to": 100}, {"key": "100-200", "from": 100, "to": 200}, {"key": "200+", "from": 200} ] }, { "field": "specifications", "size": 10, "type": "terms" } ] } ``` ### 7.4 规格过滤与分面 **需求**: 搜索"手机",筛选color为"white"的商品 ```json { "query": "手机", "size": 20, "language": "zh", "filters": { "specifications": { "name": "color", "value": "white" } } } ``` **需求**: 搜索"手机",筛选color为"white"且size为"256GB"的商品 ```json { "query": "手机", "size": 20, "language": "zh", "filters": { "specifications": [ {"name": "color", "value": "white"}, {"name": "size", "value": "256GB"} ] } } ``` **需求**: 搜索"手机",筛选size为"3"、"4"或"5",且color为"green"的商品 ```json { "query": "手机", "size": 20, "language": "zh", "filters": { "specifications": [ {"name": "size", "value": "3"}, {"name": "size", "value": "4"}, {"name": "size", "value": "5"}, {"name": "color", "value": "green"} ] } } ``` **需求**: 搜索"手机",获取所有规格的分面统计 ```json { "query": "手机", "size": 20, "language": "zh", "facets": [ {"field": "specifications", "size": 10, "type": "terms"} ] } ``` **需求**: 只获取"color"和"size"规格的分面统计 ```json { "query": "手机", "size": 20, "language": "zh", "facets": [ {"field": "specifications.color", "size": 20, "type": "terms"}, {"field": "specifications.size", "size": 15, "type": "terms"} ] } ``` **需求**: 搜索"手机",筛选类目和规格,并获取对应的分面统计 ```json { "query": "手机", "size": 20, "language": "zh", "filters": { "category_name": "手机", "specifications": { "name": "color", "value": "white" } }, "facets": [ {"field": "category1_name", "size": 15, "type": "terms"}, {"field": "category2_name", "size": 10, "type": "terms"}, {"field": "specifications.color", "size": 20, "type": "terms"}, {"field": "specifications.size", "size": 15, "type": "terms"} ] } ``` ### 7.5 SKU筛选 **需求**: 搜索"芭比娃娃",每个SPU下按颜色筛选,每种颜色只显示一个SKU ```json { "query": "芭比娃娃", "size": 20, "sku_filter_dimension": ["color"] } ``` **说明**: - 如果 `option1_name` 为 `"color"`,则使用 `sku_filter_dimension: ["color"]` 可以按颜色分组 - 每个SPU下,每种颜色只会返回第一个SKU - 如果维度不匹配,返回所有SKU(不进行过滤) ### 7.6 布尔表达式搜索 **需求**: 搜索包含"手机"和"智能"的商品,排除"二手" ```json { "query": "手机 AND 智能 ANDNOT 二手", "size": 20 } ``` ### 7.7 分页查询 **需求**: 获取第2页结果(每页20条) ```json { "query": "手机", "size": 20, "from": 20 } ``` --- ## 数据模型 ### 8.1 商品字段定义 | 字段名 | 类型 | 描述 | |--------|------|------| | `tenant_id` | keyword | 租户ID(多租户隔离) | | `spu_id` | keyword | SPU ID | | `title_zh`, `title_en` | text | 商品标题(中英文) | | `brief_zh`, `brief_en` | text | 商品短描述(中英文) | | `description_zh`, `description_en` | text | 商品详细描述(中英文) | | `vendor_zh`, `vendor_en` | text | 供应商/品牌(中英文,含keyword子字段) | | `category_path_zh`, `category_path_en` | text | 类目路径(中英文,用于搜索) | | `category_name_zh`, `category_name_en` | text | 类目名称(中英文,用于搜索) | | `category_id` | keyword | 类目ID | | `category_name` | keyword | 类目名称(用于过滤) | | `category_level` | integer | 类目层级 | | `category1_name`, `category2_name`, `category3_name` | keyword | 多级类目名称(用于过滤和分面) | | `tags` | keyword | 标签(数组) | | `specifications` | nested | 规格(嵌套对象数组) | | `option1_name`, `option2_name`, `option3_name` | keyword | 选项名称 | | `min_price`, `max_price` | float | 最低/最高价格 | | `compare_at_price` | float | 原价 | | `sku_prices` | float | SKU价格列表(数组) | | `sku_weights` | long | SKU重量列表(数组) | | `sku_weight_units` | keyword | SKU重量单位列表(数组) | | `total_inventory` | long | 总库存 | | `sales` | long | 销量(展示销量) | | `skus` | nested | SKU详细信息(嵌套对象数组) | | `create_time`, `update_time` | date | 创建/更新时间 | | `title_embedding` | dense_vector | 标题向量(1024维,仅用于搜索) | | `image_embedding` | nested | 图片向量(嵌套,仅用于搜索) | > 所有租户共享统一的索引结构。文本字段支持中英文双语,后端根据 `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 常用字段列表 #### 过滤字段 - `category_name`: 类目名称 - `category1_name`, `category2_name`, `category3_name`: 多级类目 - `category_id`: 类目ID - `vendor_zh.keyword`, `vendor_en.keyword`: 供应商/品牌(使用keyword子字段) - `tags`: 标签(keyword类型) - `option1_name`, `option2_name`, `option3_name`: 选项名称 - `specifications`: 规格过滤(嵌套字段,格式见[过滤器详解](#33-过滤器详解)) #### 范围字段 - `min_price`: 最低价格 - `max_price`: 最高价格 - `compare_at_price`: 原价 - `create_time`: 创建时间 - `update_time`: 更新时间 #### 排序字段 - `price`: 价格(后端自动根据sort_order映射:asc→min_price,desc→max_price) - `sales`: 销量 - `create_time`: 创建时间 - `update_time`: 更新时间 - `relevance_score`: 相关性分数(默认,不指定sort_by时使用) **注意**: 前端只需传 `price`,后端会自动处理: - `sort_by: "price"` + `sort_order: "asc"` → 按 `min_price` 升序(价格从低到高) - `sort_by: "price"` + `sort_order: "desc"` → 按 `max_price` 降序(价格从高到低) ### 8.4 支持的分析器 | 分析器 | 语言 | 描述 | |--------|------|------| | `index_ansj` | 中文 | 中文索引分析器(用于中文字段) | | `query_ansj` | 中文 | 中文查询分析器(用于中文字段) | | `hanlp_index` ⚠️ TODO(暂不支持) | 中文 | 中文索引分析器(用于中文字段) | | `hanlp_standard` ⚠️ TODO(暂不支持) | 中文 | 中文查询分析器(用于中文字段) | | `english` | 英文 | 标准英文分析器(用于英文字段) | | `lowercase` | - | 小写标准化器(用于keyword子字段) |