MIGRATION_GUIDE_V3.md
9.26 KB
API v3.0 迁移指南
本文档帮助你从旧版 API 迁移到 v3.0。
重要变更概述
v3.0 是一个不向后兼容的版本,主要变更包括:
- ❌ 移除 硬编码的
price_ranges参数 - ❌ 移除
aggregations参数(ES DSL) - ✅ 新增
range_filters参数 - ✅ 新增
facets参数(简化接口) - ✅ 新增 标准化的分面响应格式
迁移步骤
第一步:更新过滤器参数
旧代码(v2.x)
{
"query": "玩具",
"filters": {
"price_ranges": ["0-50", "50-100"]
}
}
新代码(v3.0)
{
"query": "玩具",
"range_filters": {
"price": {
"gte": 50,
"lte": 100
}
}
}
迁移对照表
| 旧格式 | 新格式 |
|---|---|
"price_ranges": ["0-50"] |
"price": {"lt": 50} |
"price_ranges": ["50-100"] |
"price": {"gte": 50, "lt": 100} |
"price_ranges": ["100-200"] |
"price": {"gte": 100, "lt": 200} |
"price_ranges": ["200+"] |
"price": {"gte": 200} |
第二步:更新聚合参数
旧代码(v2.x)
{
"query": "玩具",
"aggregations": {
"category_stats": {
"terms": {
"field": "categoryName_keyword",
"size": 15
}
},
"brand_stats": {
"terms": {
"field": "brandName_keyword",
"size": 15
}
}
}
}
新代码(v3.0)- 简单模式
{
"query": "玩具",
"facets": ["categoryName_keyword", "brandName_keyword"]
}
新代码(v3.0)- 高级模式
{
"query": "玩具",
"facets": [
{
"field": "categoryName_keyword",
"size": 15,
"type": "terms"
},
{
"field": "brandName_keyword",
"size": 15,
"type": "terms"
}
]
}
第三步:更新响应解析
旧代码(v2.x)
// JavaScript
const data = await response.json();
// 解析聚合结果(ES 原始格式)
if (data.aggregations && data.aggregations.category_stats) {
data.aggregations.category_stats.buckets.forEach(bucket => {
console.log(bucket.key, bucket.doc_count);
});
}
# Python
data = response.json()
# 解析聚合结果(ES 原始格式)
if 'aggregations' in data and 'category_stats' in data['aggregations']:
for bucket in data['aggregations']['category_stats']['buckets']:
print(bucket['key'], bucket['doc_count'])
新代码(v3.0)
// JavaScript
const data = await response.json();
// 解析分面结果(标准化格式)
if (data.facets) {
data.facets.forEach(facet => {
console.log(`${facet.label} (${facet.type}):`);
facet.values.forEach(value => {
console.log(` ${value.label}: ${value.count}`);
});
});
}
# Python
data = response.json()
# 解析分面结果(标准化格式)
if 'facets' in data:
for facet in data['facets']:
print(f"{facet['label']} ({facet['type']}):")
for value in facet['values']:
print(f" {value['label']}: {value['count']}")
完整迁移示例
示例 1:带价格过滤的搜索
旧代码
import requests
response = requests.post('http://localhost:6002/search/', json={
"query": "玩具",
"size": 20,
"filters": {
"categoryName_keyword": "玩具",
"price_ranges": ["50-100", "100-200"]
},
"aggregations": {
"brand_stats": {
"terms": {
"field": "brandName_keyword",
"size": 15
}
}
}
})
data = response.json()
# 解析聚合
for bucket in data['aggregations']['brand_stats']['buckets']:
print(f"{bucket['key']}: {bucket['doc_count']}")
新代码
import requests
response = requests.post('http://localhost:6002/search/', json={
"query": "玩具",
"size": 20,
"filters": {
"categoryName_keyword": "玩具"
},
"range_filters": {
"price": {
"gte": 50,
"lte": 200
}
},
"facets": [
{"field": "brandName_keyword", "size": 15}
]
})
data = response.json()
# 解析分面
for facet in data['facets']:
if facet['field'] == 'brandName_keyword':
for value in facet['values']:
print(f"{value['label']}: {value['count']}")
示例 2:前端 JavaScript 迁移
旧代码
// 构建请求
const requestBody = {
query: "玩具",
filters: {
price_ranges: ["50-100"]
},
aggregations: {
category_stats: {
terms: {
field: "categoryName_keyword",
size: 15
}
}
}
};
// 发送请求
const response = await fetch('/search/', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify(requestBody)
});
const data = await response.json();
// 显示聚合结果
const buckets = data.aggregations.category_stats.buckets;
buckets.forEach(bucket => {
console.log(`${bucket.key}: ${bucket.doc_count}`);
});
新代码
// 构建请求
const requestBody = {
query: "玩具",
range_filters: {
price: {
gte: 50,
lte: 100
}
},
facets: [
{field: "categoryName_keyword", size: 15}
]
};
// 发送请求
const response = await fetch('/search/', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify(requestBody)
});
const data = await response.json();
// 显示分面结果
data.facets.forEach(facet => {
console.log(`${facet.label}:`);
facet.values.forEach(value => {
console.log(` ${value.label}: ${value.count}`);
});
});
字段映射对照
请求字段
| v2.x | v3.0 | 说明 |
|---|---|---|
filters.price_ranges |
range_filters.price |
价格范围过滤 |
aggregations |
facets |
分面配置 |
| - | range_filters.* |
任意数值字段范围过滤 |
响应字段
| v2.x | v3.0 | 说明 |
|---|---|---|
aggregations |
facets |
分面结果 |
aggregations.*.buckets[].key |
facets[].values[].value |
分面值 |
aggregations.*.buckets[].doc_count |
facets[].values[].count |
文档数量 |
| - | facets[].values[].label |
显示标签 |
| - | facets[].values[].selected |
是否选中 |
| - | facets[].label |
分面名称 |
| - | facets[].type |
分面类型 |
常见问题
Q1: 我的代码使用了 price_ranges,如何迁移?
A: 使用 range_filters 替代:
# 旧
filters = {"price_ranges": ["50-100"]}
# 新
range_filters = {"price": {"gte": 50, "lte": 100}}
Q2: 我使用了 ES 聚合语法,如何迁移?
A: 使用简化的 facets 配置:
# 旧
aggregations = {
"my_agg": {
"terms": {
"field": "categoryName_keyword",
"size": 15
}
}
}
# 新(简单模式)
facets = ["categoryName_keyword"]
# 新(高级模式)
facets = [
{"field": "categoryName_keyword", "size": 15}
]
Q3: 响应中的 aggregations 字段去哪了?
A: 已改名为 facets,并且格式标准化了:
# 旧
for bucket in data['aggregations']['category_stats']['buckets']:
print(bucket['key'], bucket['doc_count'])
# 新
for facet in data['facets']:
for value in facet['values']:
print(value['value'], value['count'])
Q4: 如何实现多个不连续的价格范围?
A: v3.0 不支持单字段多个不连续范围。请使用布尔查询或分多次查询:
# 方案1:分两次查询
result1 = search(query="玩具", range_filters={"price": {"lt": 50}})
result2 = search(query="玩具", range_filters={"price": {"gte": 200}})
# 方案2:使用范围分面统计(不过滤,只统计)
facets = [{
"field": "price",
"type": "range",
"ranges": [
{"key": "低价", "to": 50},
{"key": "高价", "from": 200}
]
}]
Q5: 我需要继续使用旧接口,怎么办?
A: v3.0 不提供向后兼容。建议:
- 尽快迁移到新接口
- 如果暂时无法迁移,请继续使用 v2.x 版本
- 参考本文档快速完成迁移(通常只需要 1-2 小时)
迁移检查清单
完成以下检查项,确保迁移完整:
后端代码
- [ ] 移除所有
price_ranges参数的使用 - [ ] 将范围过滤改为
range_filters - [ ] 将
aggregations改为facets - [ ] 更新响应解析,使用
facets而不是aggregations
前端代码
- [ ] 更新搜索请求体,使用新参数
- [ ] 更新状态管理,添加
rangeFilters - [ ] 重写分面结果显示逻辑
- [ ] 移除所有 ES DSL 聚合代码
测试
- [ ] 测试简单搜索功能
- [ ] 测试范围过滤功能
- [ ] 测试分面搜索功能
- [ ] 测试组合查询功能
- [ ] 测试排序功能
文档
- [ ] 更新 API 调用文档
- [ ] 更新代码注释
- [ ] 通知团队成员新的 API 变更
获取帮助
- API 文档:
API_DOCUMENTATION.md - 使用示例:
API_EXAMPLES.md - 测试脚本:
test_new_api.py - 变更日志:
CHANGES.md
迁移难度: ⭐⭐ (简单到中等)
预计时间: 1-2 小时
优势: 更灵活、更通用、更易用的 API
版本: 3.0
日期: 2024-11-12