Tìm kiếm sản phẩm
API tìm kiếm sản phẩm nâng cao với bộ lọc, phân trang và aggregation (Facets).
Endpoint
POST /site/products/search
Headers
| Key | Value | Bắt buộc | Mô tả |
|---|---|---|---|
SiteTenantId | {tenant_id} | Có | ID của công ty/tenant. |
Workflow & Logic
API này hoạt động theo mô hình Search-First, truy xuất dữ liệu từ chỉ mục tìm kiếm ElasticSearch của shop để đảm bảo hiệu năng cao khi lọc và thống kê (aggregation). Sau khi có danh sách ID từ ES, hệ thống sẽ Enrich (làm giàu) dữ liệu từ Database để đảm bảo tính chính xác nhất về giá, tồn kho và các thông tin chi tiết.
Quy trình xử lý (Internal Processing)
-
Khởi tạo (Initialization):
- Xác định
company_idhiện tại. - Tải cấu hình hệ thống (
Setting), quan trọng nhất làwebsite_price_policy_idđể xác định chính sách giá áp dụng cho website (áp dụng chung cho mọi khách, không phụ thuộc khách đăng nhập).
- Xác định
-
Xử lý Bộ lọc (Filter Processing):
-
Visibility:
- Mặc định chỉ lấy sản phẩm có trạng thái
VISIBILITY_SHOWvàVISIBILITY_CATALOG_ONLY. - Nếu có từ khóa
keyword, bổ sung thêmVISIBILITY_SEARCH_ONLY. with_attachment=1: Cho phép hiển thị sản phẩm quà tặng/phụ kiện (VISIBILITY_ATTACHMENT).
- Mặc định chỉ lấy sản phẩm có trạng thái
-
Price Range: Phân tích chuỗi
price(VD:0-100000.200000-500000) thành các khoảng giá để query ES. -
Product Options: Giải mã chuỗi
productoption(VD:optionID:valID1,valID2) để lọc theo thuộc tính động. -
String Facet: Lọc theo các thuộc tính dạng chuỗi (dynamic attribute) gửi qua request body.
-
Chỉ lấy sản phẩm đang hoạt động (
status = 3) và khớp tất cả điều kiện lọc.
-
-
Truy vấn Search Engine (ES Query):
- Thực hiện query tới ElasticSearch với các tiêu chí lọc.
- Tính toán Aggregations (Facets) theo yêu cầu từ tham số
aggs(VD: đếm số lượng theo Brand, Category).
-
Làm giàu dữ liệu (Data Enrichment):
-
Từ danh sách ID trả về bởi ES, hệ thống lấy dữ liệu thẻ sản phẩm (product card) mới nhất của từng sản phẩm (sản phẩm đã bị xóa sẽ bị loại khỏi
items):- Variants & Pricing: Tính toán giá thực tế dựa trên Policy (Giá chính sách > Giá UOM > Giá gốc).
- Selectable Options: Tính toán ma trận tùy chọn (Màu/Size) khả dụng dựa trên các Variants thực tế. Giúp Frontend ẩn các nút không có hàng.
- Social Videos: Tự động parse link (TikTok/Youtube) thành ID video nhúng.
-
Query Parameters
Mặc dù dùng phương thức POST, các tham số lọc dưới đây được đọc từ query string (URL). Riêng string_facet được gửi trong request body (JSON).
| Tên | Kiểu | Bắt buộc | Mô tả |
|---|---|---|---|
keyword | string | Không | Từ khóa tìm kiếm. |
category_id | integer | Không | Lọc theo ID danh mục chính xác. |
category_id_list | string | Không | Lọc theo danh sách ID danh mục (cách nhau dấu phẩy). |
brand | string | Không | Lọc theo danh sách ID thương hiệu (cách nhau dấu phẩy). |
price | string | Không | Lọc theo khoảng giá. VD: 0-100000 hoặc 0-100000.200000-500000 (nhiều khoảng). Mỗi khoảng phải có from <= to và to >= 100000, khoảng không hợp lệ bị bỏ qua. |
productoption | string | Không | Lọc theo thuộc tính. Format: optionID:valueID,valueID|optionID2:valueID. |
ids | string | Không | Lọc theo danh sách ID sản phẩm cụ thể (cách nhau dấu phẩy, tối đa 100 ID). |
aggs | string | Không | Danh sách aggregation cần lấy. VD: agg_brand,agg_category. Có thể chỉ định size: agg_brand:10 (mặc định 7). Giá trị hỗ trợ: agg_brand, agg_category, agg_string_facet, agg_product_option. |
sorter | integer | Không | Mã sắp xếp (xem bảng Sorter bên dưới). |
page | integer | Không | Trang hiện tại. Mặc định là 1; giá trị không phải số hoặc nhỏ hơn 1 được coi là 1. Chỉ duyệt được 10.000 kết quả đầu (page × limit ≤ 10.000): trang xa hơn trả items: [] (vẫn có total, aggs), không báo lỗi. Cần nhiều hơn thì thu hẹp bằng bộ lọc. |
limit | integer | Không | Số kết quả mỗi trang. Mặc định và tối đa là 50 (giá trị âm / lớn hơn 50 dùng 50). |
with_attachment | integer | Không | 1: Bao gồm sản phẩm đính kèm; 0: Ẩn (Mặc định). |
Request Body
| Tên | Kiểu | Bắt buộc | Mô tả |
|---|---|---|---|
string_facet | array | Không | Lọc theo thuộc tính động dạng chuỗi (string facet). Mỗi phần tử có dạng \{"name": "Chất liệu", "value": ["Cotton", "Lụa"]\}. |
Sorter
| Giá trị | Mô tả |
|---|---|
1 (hoặc không truyền) | Mặc định: có keyword thì theo độ liên quan; không có thì theo sản phẩm mới nhất (và thứ tự trong danh mục khi có category_id). |
3 | Giá tăng dần |
5 | Giá giảm dần |
7 | Phần trăm giảm giá giảm dần |
9 | Mới nhất |
11 | Cũ nhất |
13 | Tên A → Z |
15 | Tên Z → A |
17 | Điểm đánh giá tăng dần |
19 | Điểm đánh giá giảm dần |
21 | Số lượt đánh giá tăng dần |
23 | Số lượt đánh giá giảm dần |
Response Schema
HTTP 200 - JSON Object
{
"total": 100,
"currentpage": 1,
"limit": 50,
"items": [
{
"id": 10,
"name": "Iphone 15 Pro Max",
"type": 1,
"status": 3,
"seo_url": "iphone-15-pro-max",
"brand_id": 5,
"badge": "Mới",
"category": {
"id": 1,
"name": "Điện thoại",
"seo_url": "dien-thoai",
"parent_id": 0
},
"selectable_options": [],
"variants": [],
"thumbnails": [],
"gallery": [],
"social_videos": [],
"product_uoms": [],
"info_promotion_note": "Giảm 10%",
"avg_rating": 4.5,
"count_rating": 100,
"default_variant_id": 100,
"weight_type": 0,
"weight_sale_mode": 0,
"pricing_type": 0,
"procurement_type": 0,
"allow_preorder": 0,
"sell_on_zero": 0,
"_score": 1.5
}
],
"aggs": [
{
"type": "agg_brand",
"name": "agg_brand",
"display_order": 1,
"count_other": 0,
"stats_bucket": 0,
"buckets": [
{
"id": 50,
"count": 10,
"name": "Samsung",
"more_info": "{\"seo_url\": \"...\"}"
}
]
}
]
}Response Fields
| Trường | Kiểu | Mô tả |
|---|---|---|
total | integer | Tổng số kết quả tìm được |
currentpage | integer | Trang hiện tại |
limit | integer | Số kết quả mỗi trang |
items | array | Danh sách sản phẩm. Xem Product Object (chỉ bao gồm các trường Listing) |
aggs | array | Danh sách Aggregation (Facets). Xem Aggregation Schema |
Aggregation Schema
Mỗi item trong aggs chứa kết quả thống kê cho một loại aggregation.
| Trường | Kiểu | Mô tả |
|---|---|---|
type | string | Loại aggregation (agg_brand, agg_category, agg_string_facet, agg_product_option) |
name | string | Tên aggregation. Với agg_string_facet và agg_product_option, đây là tên thuộc tính (VD: "Chất liệu") |
display_order | integer | Thứ tự hiển thị |
count_other | integer | Số lượng kết quả nằm ngoài top N (overflow) |
stats_bucket | integer/object | Thông tin thống kê bucket (min/max cho khoảng giá...) |
buckets | array | Danh sách giá trị. Xem bảng Bucket bên dưới |
Bucket Item
| Trường | Kiểu | Mô tả |
|---|---|---|
id | string/integer | ID của giá trị (Category ID, Brand ID, hoặc tên thuộc tính) |
count | integer | Số lượng sản phẩm khớp |
name | string | Tên hiển thị (tự enrich từ DB cho agg_category và agg_brand) |
more_info | string | JSON chứa thông tin bổ sung (VD: seo_url cho category) |
Aggregation Types
| Type | Mô tả | Enrichment |
|---|---|---|
agg_category | Thống kê theo danh mục | name = tên danh mục, more_info chứa seo_url |
agg_brand | Thống kê theo thương hiệu | name = tên thương hiệu |
agg_string_facet | Thống kê theo thuộc tính động (chuỗi) | name = giá trị thuộc tính |
agg_product_option | Thống kê theo product option | name = giá trị option |
Các lỗi thường gặp
| HTTP | Mã lỗi | Mô tả |
|---|---|---|
| 503 | error_search_unavailable | Tìm kiếm tạm thời không thực hiện được. Thử lại sau; nếu lặp lại, liên hệ hỗ trợ. Phản hồi không kèm chi tiết kỹ thuật. |
Shop chưa có sản phẩm nào không phải lỗi: trả total: 0, items: []. Tham số phân trang lạ (trang quá xa, số quá lớn) cũng
không phải lỗi (xem page ở trên).