# API 使用示例 本文档提供了搜索引擎 API 的详细使用示例,包括各种常见场景和最佳实践。 --- ## 目录 1. [基础搜索](#基础搜索) 2. [过滤器使用](#过滤器使用) 3. [分面搜索](#分面搜索) 4. [排序](#排序) 5. [图片搜索](#图片搜索) 6. [布尔表达式](#布尔表达式) 7. [完整示例](#完整示例) --- ## 基础搜索 ### 示例 1:最简单的搜索 ```bash curl -X POST "http://localhost:6002/search/" \ -H "Content-Type: application/json" \ -d '{ "query": "芭比娃娃" }' ``` **响应**: ```json { "hits": [...], "total": 118, "max_score": 8.5, "took_ms": 45, "query_info": { "original_query": "芭比娃娃", "detected_language": "zh", "translations": {"en": "barbie doll"} } } ``` ### 示例 2:指定返回数量 ```bash curl -X POST "http://localhost:6002/search/" \ -H "Content-Type: application/json" \ -d '{ "query": "玩具", "size": 50 }' ``` ### 示例 3:分页查询 ```bash # 第1页(0-19) curl -X POST "http://localhost:6002/search/" \ -H "Content-Type: application/json" \ -d '{ "query": "玩具", "size": 20, "from": 0 }' # 第2页(20-39) curl -X POST "http://localhost:6002/search/" \ -H "Content-Type: application/json" \ -d '{ "query": "玩具", "size": 20, "from": 20 }' ``` --- ## 过滤器使用 ### 精确匹配过滤器 #### 示例 1:单值过滤 ```bash curl -X POST "http://localhost:6002/search/" \ -H "Content-Type: application/json" \ -d '{ "query": "玩具", "filters": { "category.keyword": "玩具" } }' ``` #### 示例 2:多值过滤(OR 逻辑) ```bash curl -X POST "http://localhost:6002/search/" \ -H "Content-Type: application/json" \ -d '{ "query": "娃娃", "filters": { "category.keyword": ["玩具", "益智玩具", "儿童玩具"] } }' ``` 说明:匹配类目为"玩具" **或** "益智玩具" **或** "儿童玩具"的商品。 #### 示例 3:多字段过滤(AND 逻辑) ```bash curl -X POST "http://localhost:6002/search/" \ -H "Content-Type: application/json" \ -d '{ "query": "娃娃", "filters": { "category.keyword": "玩具", "vendor.keyword": "美泰" } }' ``` 说明:必须同时满足"类目=玩具" **并且** "品牌=美泰"。 ### 范围过滤器 #### 示例 1:价格范围 ```bash curl -X POST "http://localhost:6002/search/" \ -H "Content-Type: application/json" \ -d '{ "query": "玩具", "range_filters": { "price": { "gte": 50, "lte": 200 } } }' ``` 说明:价格在 50-200 元之间(包含边界)。 #### 示例 2:只设置下限 ```bash curl -X POST "http://localhost:6002/search/" \ -H "Content-Type: application/json" \ -d '{ "query": "玩具", "range_filters": { "price": { "gte": 100 } } }' ``` 说明:价格 ≥ 100 元。 #### 示例 3:只设置上限 ```bash curl -X POST "http://localhost:6002/search/" \ -H "Content-Type: application/json" \ -d '{ "query": "玩具", "range_filters": { "price": { "lt": 50 } } }' ``` 说明:价格 < 50 元(不包含50)。 #### 示例 4:多字段范围过滤 ```bash curl -X POST "http://localhost:6002/search/" \ -H "Content-Type: application/json" \ -d '{ "query": "玩具", "range_filters": { "price": { "gte": 50, "lte": 200 }, "days_since_last_update": { "lte": 30 } } }' ``` 说明:价格在 50-200 元 **并且** 最近30天内更新过。 ### 组合过滤器 ```bash curl -X POST "http://localhost:6002/search/" \ -H "Content-Type: application/json" \ -d '{ "query": "玩具", "filters": { "category.keyword": ["玩具", "益智玩具"], "vendor.keyword": "乐高" }, "range_filters": { "price": { "gte": 50, "lte": 500 } } }' ``` 说明:类目是"玩具"或"益智玩具" **并且** 品牌是"乐高" **并且** 价格在 50-500 元之间。 --- ## 分面搜索 ### 简单模式 #### 示例 1:基础分面 ```bash curl -X POST "http://localhost:6002/search/" \ -H "Content-Type: application/json" \ -d '{ "query": "玩具", "size": 20, "facets": ["category.keyword", "vendor.keyword"] }' ``` **响应**: ```json { "hits": [...], "total": 118, "facets": [ { "field": "category.keyword", "label": "category.keyword", "type": "terms", "values": [ {"value": "玩具", "count": 85, "selected": false}, {"value": "益智玩具", "count": 33, "selected": false} ] }, { "field": "vendor.keyword", "label": "vendor.keyword", "type": "terms", "values": [ {"value": "乐高", "count": 42, "selected": false}, {"value": "美泰", "count": 28, "selected": false} ] } ] } ``` ### 高级模式 #### 示例 1:自定义分面大小 ```bash curl -X POST "http://localhost:6002/search/" \ -H "Content-Type: application/json" \ -d '{ "query": "玩具", "facets": [ { "field": "category.keyword", "size": 20, "type": "terms" }, { "field": "vendor.keyword", "size": 30, "type": "terms" } ] }' ``` #### 示例 2:范围分面 ```bash curl -X POST "http://localhost:6002/search/" \ -H "Content-Type: application/json" \ -d '{ "query": "玩具", "facets": [ { "field": "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} ] } ] }' ``` **响应**: ```json { "facets": [ { "field": "price", "label": "price", "type": "range", "values": [ {"value": "0-50", "count": 23, "selected": false}, {"value": "50-100", "count": 45, "selected": false}, {"value": "100-200", "count": 38, "selected": false}, {"value": "200+", "count": 12, "selected": false} ] } ] } ``` #### 示例 3:混合分面(Terms + Range) ```bash curl -X POST "http://localhost:6002/search/" \ -H "Content-Type: application/json" \ -d '{ "query": "玩具", "facets": [ {"field": "category.keyword", "size": 15}, {"field": "vendor.keyword", "size": 15}, { "field": "price", "type": "range", "ranges": [ {"key": "低价", "to": 50}, {"key": "中价", "from": 50, "to": 200}, {"key": "高价", "from": 200} ] } ] }' ``` --- ## 排序 ### 示例 1:按价格排序(升序) ```bash curl -X POST "http://localhost:6002/search/" \ -H "Content-Type: application/json" \ -d '{ "query": "玩具", "size": 20, "sort_by": "min_price", "sort_order": "asc" }' ``` ### 示例 2:按创建时间排序(降序) ```bash curl -X POST "http://localhost:6002/search/" \ -H "Content-Type: application/json" \ -d '{ "query": "玩具", "size": 20, "sort_by": "create_time", "sort_order": "desc" }' ``` ### 示例 3:排序+过滤 ```bash curl -X POST "http://localhost:6002/search/" \ -H "Content-Type: application/json" \ -d '{ "query": "玩具", "filters": { "category.keyword": "益智玩具" }, "sort_by": "min_price", "sort_order": "asc" }' ``` --- ## 图片搜索 ### 示例 1:基础图片搜索 ```bash curl -X POST "http://localhost:6002/search/image" \ -H "Content-Type: application/json" \ -d '{ "image_url": "https://example.com/barbie.jpg", "size": 20 }' ``` ### 示例 2:图片搜索+过滤器 ```bash curl -X POST "http://localhost:6002/search/image" \ -H "Content-Type: application/json" \ -d '{ "image_url": "https://example.com/barbie.jpg", "size": 20, "filters": { "category.keyword": "玩具" }, "range_filters": { "price": { "lte": 100 } } }' ``` --- ## 布尔表达式 ### 示例 1:AND 查询 ```bash curl -X POST "http://localhost:6002/search/" \ -H "Content-Type: application/json" \ -d '{ "query": "玩具 AND 乐高" }' ``` 说明:必须同时包含"玩具"和"乐高"。 ### 示例 2:OR 查询 ```bash curl -X POST "http://localhost:6002/search/" \ -H "Content-Type: application/json" \ -d '{ "query": "芭比 OR 娃娃" }' ``` 说明:包含"芭比"或"娃娃"即可。 ### 示例 3:ANDNOT 查询(排除) ```bash curl -X POST "http://localhost:6002/search/" \ -H "Content-Type: application/json" \ -d '{ "query": "玩具 ANDNOT 电动" }' ``` 说明:包含"玩具"但不包含"电动"。 ### 示例 4:复杂布尔表达式 ```bash curl -X POST "http://localhost:6002/search/" \ -H "Content-Type: application/json" \ -d '{ "query": "玩具 AND (乐高 OR 芭比) ANDNOT 电动" }' ``` 说明:必须包含"玩具",并且包含"乐高"或"芭比",但不包含"电动"。 ### 示例 5:域查询 ```bash curl -X POST "http://localhost:6002/search/" \ -H "Content-Type: application/json" \ -d '{ "query": "brand:乐高" }' ``` 说明:在品牌域中搜索"乐高"。 --- ## 完整示例 ### Python 完整示例 ```python #!/usr/bin/env python3 import requests import json API_URL = "http://localhost:6002/search/" def search_products( query, size=20, from_=0, filters=None, range_filters=None, facets=None, sort_by=None, sort_order="desc", debug=False ): """执行搜索查询""" payload = { "query": query, "size": size, "from": from_ } if filters: payload["filters"] = filters if range_filters: payload["range_filters"] = range_filters if facets: payload["facets"] = facets if sort_by: payload["sort_by"] = sort_by payload["sort_order"] = sort_order if debug: payload["debug"] = debug response = requests.post(API_URL, json=payload) response.raise_for_status() return response.json() # 示例 1:简单搜索 result = search_products("芭比娃娃", size=10) print(f"找到 {result['total']} 个结果") for hit in result['hits'][:3]: product = hit['_source'] print(f" - {product['name']}: ¥{product.get('price', 'N/A')}") # 示例 2:带过滤和分面的搜索 result = search_products( query="玩具", size=20, filters={ "category.keyword": ["玩具", "益智玩具"] }, range_filters={ "price": {"gte": 50, "lte": 200} }, facets=[ {"field": "vendor.keyword", "size": 15}, {"field": "category.keyword", "size": 15}, { "field": "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} ] } ], sort_by="min_price", sort_order="asc" ) # 显示分面结果 print(f"\n分面统计:") for facet in result.get('facets', []): print(f"\n{facet['label']} ({facet['type']}):") for value in facet['values'][:5]: selected_mark = "✓" if value['selected'] else " " print(f" [{selected_mark}] {value['label']}: {value['count']}") # 示例 3:分页查询 page = 1 page_size = 20 total_pages = 5 for page in range(1, total_pages + 1): result = search_products( query="玩具", size=page_size, from_=(page - 1) * page_size ) print(f"\n第 {page} 页:") for hit in result['hits']: product = hit['_source'] print(f" - {product['name']}") ``` ### JavaScript 完整示例 ```javascript // 搜索引擎客户端 class SearchClient { constructor(baseUrl) { this.baseUrl = baseUrl; } async search({ query, size = 20, from = 0, filters = null, rangeFilters = null, facets = null, sortBy = null, sortOrder = 'desc', debug = false }) { const payload = { query, size, from }; if (filters) payload.filters = filters; if (rangeFilters) payload.range_filters = rangeFilters; if (facets) payload.facets = facets; if (sortBy) { payload.sort_by = sortBy; payload.sort_order = sortOrder; } if (debug) payload.debug = debug; const response = await fetch(`${this.baseUrl}/search/`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) }); if (!response.ok) { throw new Error(`HTTP ${response.status}: ${response.statusText}`); } return await response.json(); } async searchByImage(imageUrl, options = {}) { const payload = { image_url: imageUrl, size: options.size || 20, filters: options.filters || null, range_filters: options.rangeFilters || null }; const response = await fetch(`${this.baseUrl}/search/image`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) }); if (!response.ok) { throw new Error(`HTTP ${response.status}: ${response.statusText}`); } return await response.json(); } } // 使用示例 const client = new SearchClient('http://localhost:6002'); // 简单搜索 const result1 = await client.search({ query: "芭比娃娃", size: 20 }); console.log(`找到 ${result1.total} 个结果`); // 带过滤和分面的搜索 const result2 = await client.search({ query: "玩具", size: 20, filters: { category.keyword: ["玩具", "益智玩具"] }, rangeFilters: { price: { gte: 50, lte: 200 } }, facets: [ { field: "vendor.keyword", size: 15 }, { field: "category.keyword", size: 15 } ], sortBy: "price", sortOrder: "asc" }); // 显示分面结果 result2.facets.forEach(facet => { console.log(`\n${facet.label}:`); facet.values.forEach(value => { const selected = value.selected ? '✓' : ' '; console.log(` [${selected}] ${value.label}: ${value.count}`); }); }); // 显示商品 result2.hits.forEach(hit => { const product = hit._source; console.log(`${product.name} - ¥${product.price}`); }); ``` ### 前端完整示例(Vue.js 风格) ```javascript // 搜索组件 const SearchComponent = { data() { return { query: '', results: [], facets: [], filters: {}, rangeFilters: {}, total: 0, currentPage: 1, pageSize: 20 }; }, methods: { async search() { const response = await fetch('http://localhost:6002/search/', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ query: this.query, size: this.pageSize, from: (this.currentPage - 1) * this.pageSize, filters: this.filters, range_filters: this.rangeFilters, facets: [ { field: 'category.keyword', size: 15 }, { field: 'vendor.keyword', size: 15 } ] }) }); const data = await response.json(); this.results = data.hits; this.facets = data.facets || []; this.total = data.total; }, toggleFilter(field, value) { if (!this.filters[field]) { this.filters[field] = []; } const index = this.filters[field].indexOf(value); if (index > -1) { this.filters[field].splice(index, 1); if (this.filters[field].length === 0) { delete this.filters[field]; } } else { this.filters[field].push(value); } this.currentPage = 1; this.search(); }, setPriceRange(min, max) { if (min !== null || max !== null) { this.rangeFilters.price = {}; if (min !== null) this.rangeFilters.price.gte = min; if (max !== null) this.rangeFilters.price.lte = max; } else { delete this.rangeFilters.price; } this.currentPage = 1; this.search(); } } }; ``` --- ## 调试与优化 ### 启用调试模式 ```bash curl -X POST "http://localhost:6002/search/" \ -H "Content-Type: application/json" \ -d '{ "query": "玩具", "debug": true }' ``` **响应包含调试信息**: ```json { "hits": [...], "total": 118, "debug_info": { "query_analysis": { "original_query": "玩具", "normalized_query": "玩具", "rewritten_query": "玩具", "detected_language": "zh", "translations": {"en": "toy"} }, "es_query": { "query": {...}, "size": 10 }, "stage_timings": { "query_parsing": 5.3, "elasticsearch_search": 35.1, "result_processing": 4.8 } } } ``` ### 设置最小分数阈值 ```bash curl -X POST "http://localhost:6002/search/" \ -H "Content-Type: application/json" \ -d '{ "query": "玩具", "min_score": 5.0 }' ``` 说明:只返回相关性分数 ≥ 5.0 的结果。 --- ## 常见使用场景 ### 场景 1:电商分类页 ```bash # 显示某个类目下的所有商品,按价格排序,提供品牌筛选 curl -X POST "http://localhost:6002/search/" \ -H "Content-Type: application/json" \ -d '{ "query": "*", "filters": { "category.keyword": "玩具" }, "facets": [ {"field": "vendor.keyword", "size": 20}, { "field": "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} ] } ], "sort_by": "min_price", "sort_order": "asc", "size": 24 }' ``` ### 场景 2:搜索结果页 ```bash # 用户搜索关键词,提供筛选和排序 curl -X POST "http://localhost:6002/search/" \ -H "Content-Type: application/json" \ -d '{ "query": "芭比娃娃", "facets": [ {"field": "category.keyword", "size": 10}, {"field": "vendor.keyword", "size": 10}, {"field": "price", "type": "range", "ranges": [ {"key": "0-50", "to": 50}, {"key": "50-100", "from": 50, "to": 100}, {"key": "100+", "from": 100} ]} ], "size": 20 }' ``` ### 场景 3:促销专区 ```bash # 显示特定价格区间的商品 curl -X POST "http://localhost:6002/search/" \ -H "Content-Type: application/json" \ -d '{ "query": "*", "range_filters": { "price": { "gte": 50, "lte": 100 } }, "facets": ["category.keyword", "vendor.keyword"], "sort_by": "min_price", "sort_order": "asc", "size": 50 }' ``` ### 场景 4:新品推荐 ```bash # 最近更新的商品 curl -X POST "http://localhost:6002/search/" \ -H "Content-Type: application/json" \ -d '{ "query": "*", "range_filters": { "days_since_last_update": { "lte": 7 } }, "sort_by": "create_time", "sort_order": "desc", "size": 20 }' ``` --- ## 错误处理 ### 示例 1:参数错误 ```bash # 错误:range_filters 缺少操作符 curl -X POST "http://localhost:6002/search/" \ -H "Content-Type: application/json" \ -d '{ "query": "玩具", "range_filters": { "price": {} } }' ``` **响应**: ```json { "error": "Validation error", "detail": "至少需要指定一个范围边界(gte, gt, lte, lt)", "timestamp": 1699800000 } ``` ### 示例 2:空查询 ```bash # 错误:query 为空 curl -X POST "http://localhost:6002/search/" \ -H "Content-Type: application/json" \ -d '{ "query": "" }' ``` **响应**: ```json { "error": "Validation error", "detail": "query field required", "timestamp": 1699800000 } ``` --- ## 性能优化建议 ### 1. 合理使用分面 ```bash # ❌ 不推荐:请求太多分面 { "facets": [ {"field": "field1", "size": 100}, {"field": "field2", "size": 100}, {"field": "field3", "size": 100}, // ... 10+ facets ] } # ✅ 推荐:只请求必要的分面 { "facets": [ {"field": "category.keyword", "size": 15}, {"field": "vendor.keyword", "size": 15} ] } ``` ### 2. 控制返回数量 ```bash # ❌ 不推荐:一次返回太多 { "size": 100 } # ✅ 推荐:分页查询 { "size": 20, "from": 0 } ``` ### 3. 使用适当的过滤器 ```bash # ✅ 推荐:先过滤后搜索 { "query": "玩具", "filters": { "category.keyword": "玩具" } } ``` --- ## 高级技巧 ### 技巧 1:获取所有类目 ```bash # 使用通配符查询 + 分面 curl -X POST "http://localhost:6002/search/" \ -H "Content-Type: application/json" \ -d '{ "query": "*", "size": 0, "facets": [ {"field": "category.keyword", "size": 100} ] }' ``` ### 技巧 2:价格分布统计 ```bash curl -X POST "http://localhost:6002/search/" \ -H "Content-Type: application/json" \ -d '{ "query": "玩具", "size": 0, "facets": [ { "field": "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-500", "from": 200, "to": 500}, {"key": "500+", "from": 500} ] } ] }' ``` ### 技巧 3:组合多种查询类型 ```bash # 布尔表达式 + 过滤器 + 分面 + 排序 curl -X POST "http://localhost:6002/search/" \ -H "Content-Type: application/json" \ -d '{ "query": "(玩具 OR 游戏) AND 儿童 ANDNOT 电子", "filters": { "category.keyword": ["玩具", "益智玩具"] }, "range_filters": { "price": {"gte": 20, "lte": 100}, "days_since_last_update": {"lte": 30} }, "facets": [ {"field": "vendor.keyword", "size": 20} ], "sort_by": "min_price", "sort_order": "asc", "size": 20 }' ``` --- ## 测试数据 如果你需要测试数据,可以使用以下查询: ```bash # 测试类目:玩具 curl -X POST "http://localhost:6002/search/" \ -H "Content-Type: application/json" \ -d '{"query": "玩具", "size": 5}' # 测试品牌:乐高 curl -X POST "http://localhost:6002/search/" \ -H "Content-Type: application/json" \ -d '{"query": "brand:乐高", "size": 5}' # 测试布尔表达式 curl -X POST "http://localhost:6002/search/" \ -H "Content-Type: application/json" \ -d '{"query": "玩具 AND 乐高", "size": 5}' ``` --- **文档版本**: 3.0 **最后更新**: 2024-11-12 **相关文档**: `API_DOCUMENTATION.md`