Elasticsearch Bài học 23: Tổng quan Query DSL - Leaf queries vs Compound queries
Chúc mừng bạn đã hoàn thành xuất sắc 4 Module đầu tiên về kiến trúc và cấu trúc dữ liệu. Bắt đầu từ bài học này, chúng ta sẽ bước vào Phần 5: Nghệ thuật Tìm kiếm (Query DSL) – nơi định đoạt trải nghiệm của người dùng trên hệ thống e-commerce.
Nếu trong thế giới MySQL, bạn giao tiếp bằng ngôn ngữ SQL (SELECT * FROM products WHERE ...), thì trong thế giới Elasticsearch, bạn giao tiếp bằng Query DSL (Domain Specific Language) – một ngôn ngữ truy vấn được viết hoàn toàn bằng định dạng JSON.
Một câu Query DSL thực tế trên Production có thể dài tới hàng trăm, thậm chí hàng nghìn dòng JSON lồng nhau. Nhìn vào rất dễ bị "ngợp". Nhưng đừng lo, dù câu query có khổng lồ đến đâu, nó cũng chỉ được lắp ghép từ 2 khối gạch cơ bản: Leaf queries (Truy vấn lá) và Compound queries (Truy vấn phức hợp).
1. Leaf Queries (Truy vấn lá): Hạt nhân của tìm kiếm
Hãy hình dung Leaf query giống như những chiếc lá trên một cái cây. Nó là điểm tận cùng của một nhánh, không thể chứa thêm bất kỳ query nào khác bên trong nó.
Nhiệm vụ của Leaf query: Tìm kiếm một (hoặc nhiều) giá trị cụ thể trong một trường (field) cụ thể.
Hai họ Leaf queries phổ biến nhất:
-
Full-text queries (Truy vấn toàn văn bản): Dùng cho trường kiểu
text. Câu query này sẽ đi qua Analyzer (chúng ta đã học ở Bài 19) trước khi tìm trong Inverted Index.- Ví dụ:
match,match_phrase,multi_match.
- Ví dụ:
-
Term-level queries (Truy vấn cấp độ từ): Dùng cho trường kiểu
keyword, số, ngày tháng. Câu query này bỏ qua Analyzer, tìm kiếm sự trùng khớp chính xác 100% trong Inverted Index (hoặc Doc Values).- Ví dụ:
term,terms,range,exists.
- Ví dụ:
Ví dụ một Leaf Query cơ bản (Tìm các sản phẩm có giá < 300k):
JSON
GET products/_search
{
"query": {
"range": {
"price": {
"lt": 300000
}
}
}
}
2. Compound Queries (Truy vấn phức hợp): Bộ khung kết dính
Một "chiếc lá" thì không thể làm nên một hệ thống lọc sản phẩm phức tạp. Khách hàng trên Hasaki thường tìm kiếm kết hợp: "Sữa rửa mặt" (Full-text) VÀ "Thương hiệu Cetaphil" (Term) VÀ "Giá dưới 300k" (Range).
Lúc này, bạn cần Compound queries. Hãy coi chúng như những cành cây (Branch). Nhiệm vụ của chúng không phải là đi tìm dữ liệu, mà là bọc các Leaf queries (hoặc các Compound queries khác) lại với nhau theo một logic Toán học (AND, OR, NOT).
Đại diện quyền lực nhất: bool query Trong Elasticsearch, bool query tương đương với các toán tử logic trong SQL:
-
must: Tương đương AND (Phải thỏa mãn điều kiện và tham gia tính điểm Scoring). -
should: Tương đương OR (Thỏa mãn 1 trong các điều kiện, giúp tăng điểm Scoring). -
must_not: Tương đương NOT (Tuyệt đối không được chứa). -
filter: Tương đương AND nhưng chạy ở chế độ Cache, không tính điểm (Tối ưu hiệu năng kinh khủng).
Ví dụ lắp ráp một Compound Query hoàn chỉnh:
JSON
GET products/_search
{
"query": {
"bool": {
"must": [
{ "match": { "name": "Sữa rửa mặt" } } // Leaf query 1 (Full-text)
],
"filter": [
{ "term": { "brand.raw": "Cetaphil" } }, // Leaf query 2 (Term)
{ "range": { "price": { "lt": 300000 } } } // Leaf query 3 (Term)
],
"must_not": [
{ "term": { "tags": "hàng trưng bày" } } // Leaf query 4 (Term)
]
}
}
}
(Chỉ cần nhìn vào khối JSON trên, bạn có thể dễ dàng dịch nó ra tiếng người: "Hãy tìm tên chứa sữa rửa mặt, lọc đúng hãng Cetaphil, giá dưới 300k, và tuyệt đối loại bỏ các sản phẩm là hàng trưng bày").
3. Tư duy "Xếp hình Lego" trong System Design
Lợi thế tuyệt đối của JSON so với SQL là tính cấu trúc (Structured).
Khi bạn code Backend (bằng PHP Laravel hoặc Golang), bạn không bao giờ phải thực hiện việc nối chuỗi (String concatenation) cồng kềnh và dễ dính lỗi SQL Injection như kiểu query += " AND price < 300000".
Thay vào đó, bạn xây dựng một Array hoặc Map trong code, sau đó dùng các hàm điều kiện if (isset($request->price)) để push (thêm) các khối Leaf (mảng con) vào trong mảng Compound bự (chẳng hạn mảng filter). Cuối cùng, hàm json_encode() sẽ biến toàn bộ mảng đó thành một khối Query DSL chuẩn mực để bắn lên Elasticsearch. Tư duy này giúp code logic tìm kiếm của bạn cực kỳ clean (sạch) và dễ bảo trì.
Chúng ta đã có bức tranh tổng quan về cái cây Query DSL. Kể từ bài sau, chúng ta sẽ bắt đầu soi xét từng "chiếc lá". Đầu tiên sẽ là nhóm truy vấn tốc độ cao nhất, không bị Analyzer nhúng tay vào: Term-level queries.
All rights reserved