# API 快速参考 (v3.0)

## 环境与 cURL

- **默认地址**：`http://localhost:6002`（与仓库 `scripts/start_backend.sh` 一致）。
- **租户**：必须使用请求头 **`X-Tenant-ID`**（推荐）；一般不要依赖把 `tenant_id` 放在 URL 上。
- 下列命令假设已设置：

```bash
export BASE_URL="${BASE_URL:-http://localhost:6002}"
export TENANT_ID="${TENANT_ID:-163}"   # 改成你的租户ID
```

## 基础搜索

```bash
curl -sS "$BASE_URL/search/" \
  -H "Content-Type: application/json" \
  -H "X-Tenant-ID: $TENANT_ID" \
  -d '{
    "query": "芭比娃娃",
    "size": 20,
    "from": 0,
    "language": "zh"
  }'
```

等同请求：`POST /search/`，请求体含 `query`、`size`、`from`、`language`。

---

## 精确匹配过滤

在 `POST /search/` 的 JSON 里使用 `filters`（下面示例与「完整示例」可对照字段含义）：

```bash
curl -sS "$BASE_URL/search/" \
  -H "Content-Type: application/json" \
  -H "X-Tenant-ID: $TENANT_ID" \
  -d '{
    "query": "手机",
    "size": 10,
    "language": "zh",
    "filters": {
      "category_name": "手机",
      "category1_name": "服装",
      "vendor.zh.keyword": ["奇乐", "品牌A"],
      "tags": "手机",
      "specifications": {"name": "color", "value": "white"}
    }
  }'
```

### Specifications 过滤

**单个规格**：

```bash
curl -sS "$BASE_URL/search/" \
  -H "Content-Type: application/json" \
  -H "X-Tenant-ID: $TENANT_ID" \
  -d '{
    "query": "手机",
    "size": 10,
    "language": "zh",
    "filters": {
      "specifications": {"name": "color", "value": "white"}
    }
  }'
```

**多个规格（不同 name 为 AND）**：

```bash
curl -sS "$BASE_URL/search/" \
  -H "Content-Type: application/json" \
  -H "X-Tenant-ID: $TENANT_ID" \
  -d '{
    "query": "手机",
    "size": 10,
    "language": "zh",
    "filters": {
      "specifications": [
        {"name": "color", "value": "white"},
        {"name": "size", "value": "256GB"}
      ]
    }
  }'
```
说明：不同维度（不同name）是AND关系，相同维度（相同name）的多个值是OR关系。

---

## 范围过滤

```bash
curl -sS "$BASE_URL/search/" \
  -H "Content-Type: application/json" \
  -H "X-Tenant-ID: $TENANT_ID" \
  -d '{
    "query": "玩具",
    "size": 20,
    "language": "zh",
    "range_filters": {
      "min_price": {"gte": 50, "lte": 200}
    }
  }'
```

**操作符**: `gte` (>=), `gt` (>), `lte` (<=), `lt` (<)

---

## 分面搜索

### 简单模式

```bash
curl -sS "$BASE_URL/search/" \
  -H "Content-Type: application/json" \
  -H "X-Tenant-ID: $TENANT_ID" \
  -d '{
    "query": "玩具",
    "size": 20,
    "language": "zh",
    "facets": ["category1_name", "category2_name", "category3_name", "specifications"]
  }'
```

### Specifications 分面

**所有规格名称**：

```bash
curl -sS "$BASE_URL/search/" \
  -H "Content-Type: application/json" \
  -H "X-Tenant-ID: $TENANT_ID" \
  -d '{
    "query": "手机",
    "size": 10,
    "language": "zh",
    "facets": ["specifications"]
  }'
```

**指定规格名称**：

```bash
curl -sS "$BASE_URL/search/" \
  -H "Content-Type: application/json" \
  -H "X-Tenant-ID: $TENANT_ID" \
  -d '{
    "query": "手机",
    "size": 10,
    "language": "zh",
    "facets": ["specifications.color", "specifications.size", "specifications.material"]
  }'
```

### 高级模式

```bash
curl -sS "$BASE_URL/search/" \
  -H "Content-Type: application/json" \
  -H "X-Tenant-ID: $TENANT_ID" \
  -d '{
    "query": "手机",
    "size": 20,
    "language": "zh",
    "facets": [
      {"field": "category1_name", "size": 15},
      {
        "field": "min_price",
        "type": "range",
        "ranges": [
          {"key": "0-50", "to": 50},
          {"key": "50-100", "from": 50, "to": 100}
        ]
      },
      "specifications",
      "specifications.color",
      "specifications.size",
      "specifications.material"
    ]
  }'
```

---

## SKU筛选维度

**功能**: 按指定维度对每个SPU下的SKU进行分组，每组只返回第一个SKU。

```bash
curl -sS "$BASE_URL/search/" \
  -H "Content-Type: application/json" \
  -H "X-Tenant-ID: $TENANT_ID" \
  -d '{
    "query": "芭比娃娃",
    "size": 20,
    "language": "zh",
    "sku_filter_dimension": ["color"]
  }'
```

（`sku_filter_dimension` 为数组；按颜色筛选时需索引里 `option*_name` 与维度一致，见正文说明。）

**支持的维度值**:
- `option1`, `option2`, `option3`: 直接使用选项字段
- 规格名称（如 `color`, `size`）: 通过 `option1_name`、`option2_name`、`option3_name` 匹配

**示例**:
```bash
// 按选项1筛选
{"sku_filter_dimension": "option1"}

// 按颜色筛选（如果option1_name="color"）
{"sku_filter_dimension": "color"}

// 按尺寸筛选（如果option2_name="size"）
{"sku_filter_dimension": "size"}
```

**性能说明**: 在应用层过滤，不影响ES查询性能，只对返回结果进行过滤。

---

## 排序

```bash
curl -sS "$BASE_URL/search/" \
  -H "Content-Type: application/json" \
  -H "X-Tenant-ID: $TENANT_ID" \
  -d '{
    "query": "玩具",
    "size": 20,
    "language": "zh",
    "sort_by": "min_price",
    "sort_order": "asc"
  }'
```

---

## 分页

```bash
curl -sS "$BASE_URL/search/" \
  -H "Content-Type: application/json" \
  -H "X-Tenant-ID: $TENANT_ID" \
  -d '{
    "query": "手机",
    "size": 20,
    "from": 20,
    "language": "zh"
  }'
```

（第 1 页 `from: 0`，第 2 页 `from: 20`，以此类推。）

---

## 完整示例

一键联调：过滤 + 区间 + 分面 + 排序 + SKU 维度（请按实际类目/规格改 `filters`）。

```bash
curl -sS "$BASE_URL/search/" \
  -H "Content-Type: application/json" \
  -H "X-Tenant-ID: $TENANT_ID" \
  -d '{
    "query": "手机",
    "size": 20,
    "from": 0,
    "language": "zh",
    "filters": {
      "category_name": "手机",
      "category1_name": "电子产品",
      "specifications": {"name": "color", "value": "white"}
    },
    "range_filters": {
      "min_price": {"gte": 50, "lte": 200}
    },
    "facets": [
      {"field": "category1_name", "size": 15},
      {"field": "category2_name", "size": 15},
      "specifications.color",
      "specifications.size"
    ],
    "sort_by": "min_price",
    "sort_order": "asc",
    "sku_filter_dimension": ["color"]
  }'
```

---


## 响应格式

```json
{
  "results": [
    {
      "spu_id": "12345",
      "title": "商品标题",
      "brief": "短描述",
      "description": "详细描述",
      "vendor": "供应商",
      "category": "类目",
      "category_path": "类目/路径",
      "category_name": "类目名称",
      "category1_name": "一级类目",
      "category2_name": "二级类目",
      "category3_name": "三级类目",
      "tags": ["标签1", "标签2"],
      "price": 99.99,
      "compare_at_price": 149.99,
      "sku_prices": [99.99, 109.99],
      "total_inventory": 500,
      "specifications": [
        {"sku_id": "sku_001", "name": "color", "value": "white"}
      ],
      "skus": [...],  // 如果指定了sku_filter_dimension，则返回过滤后的SKU（每个维度值一个）
      "relevance_score": 8.5
    }
  ],
  "total": 118,
  "max_score": 8.5,
  "took_ms": 45,
  "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": "white",
          "label": "white",
          "count": 30,
          "selected": false
        }
      ]
    }
  ]
}
```

---

## 其他端点

**图搜**（`POST /search/image`，与文本搜一样带 `X-Tenant-ID`）：

```bash
curl -sS "$BASE_URL/search/image" \
  -H "Content-Type: application/json" \
  -H "X-Tenant-ID: $TENANT_ID" \
  -d '{
    "image_url": "https://example.com/product.jpg",
    "size": 20,
    "range_filters": {
      "min_price": {"gte": 10, "lte": 500}
    }
  }'
```

（图搜请求体仅支持 `image_url`、`size`、可选的 `filters` / `range_filters`；与文本搜的 `language` / `from` 无关。）

**搜索建议**：

```bash
curl -sS -G "$BASE_URL/search/suggestions" \
  --data-urlencode "q=芭" \
  --data-urlencode "size=5" \
  --data-urlencode "language=zh" \
  -H "X-Tenant-ID: $TENANT_ID"
```

**即时搜索**（当前实现返回 501，勿用于生产）：

```bash
curl -sS -G "$BASE_URL/search/instant" \
  --data-urlencode "q=玩具" \
  --data-urlencode "size=5" \
  -H "X-Tenant-ID: $TENANT_ID"
```

**按文档 ID 取详情**（将 `YOUR_SPU_ID` 换成真实 `spu_id`）：

```bash
curl -sS "$BASE_URL/search/YOUR_SPU_ID" \
  -H "X-Tenant-ID: $TENANT_ID"
```

**运维**：

```bash
curl -sS "$BASE_URL/admin/health"
curl -sS "$BASE_URL/admin/config"
curl -sS "$BASE_URL/admin/stats" -H "X-Tenant-ID: $TENANT_ID"
```

---


## Python 快速示例

```python
import requests

result = requests.post(
    'http://localhost:6002/search/',
    headers={'X-Tenant-ID': '2'},
    json={
        "query": "手机",
        "language": "zh",
        "filters": {"category_name": "手机"},
        "range_filters": {"min_price": {"gte": 50, "lte": 200}},
        "facets": ["category1_name", "specifications"],
        "sort_by": "min_price",
        "sort_order": "asc"
    }
).json()

print(f"找到 {result['total']} 个结果")
```

---

## JavaScript 快速示例

```javascript
const result = await fetch('http://localhost:6002/search/', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
        'X-Tenant-ID': '2'
    },
    body: JSON.stringify({
        query: "手机",
        language: "zh",
        filters: {category_name: "手机"},
        range_filters: {min_price: {gte: 50, lte: 200}},
        facets: ["category1_name", "specifications"],
        sort_by: "min_price",
        sort_order: "asc"
    })
}).then(r => r.json());

console.log(`找到 ${result.total} 个结果`);
```

---
