0

Elasticsearch Bài học 24: Term-level Queries - Tìm kiếm chính xác tuyệt đối (Term, Terms, Range, Exists)

Ở Bài 23, chúng ta đã chia "cái cây" Query DSL làm hai nhóm chính: Leaf queries và Compound queries. Hôm nay, chúng ta sẽ đi sâu vào nhánh Leaf queries có tốc độ xử lý nhanh nhất trong toàn bộ hệ sinh thái Elasticsearch: Term-level queries.

Điểm mấu chốt làm nên tốc độ của nhóm truy vấn này là chúng hoàn toàn bỏ qua Analyzer. Chúng không băm nhỏ chuỗi, không biến chữ hoa thành chữ thường. Chúng đối chiếu dữ liệu bạn gửi lên nguyên vẹn 100% với những gì đang nằm trong Inverted Index.

Nhóm này là trợ thủ đắc lực nhất cho các trường có kiểu dữ liệu là keyword, số học (numeric) và ngày tháng (date). Hãy cùng điểm qua 4 "vũ khí" quan trọng nhất.

1. term Query: Tìm kiếm chính xác 1 giá trị

Trong SQL, khi bạn dùng toán tử = (Ví dụ: WHERE brand = 'Cetaphil'), bạn muốn khớp chính xác tuyệt đối. Trong Elasticsearch, bạn dùng term.

Cú pháp:

JSON

GET products/_search
{
  "query": {
    "term": {
      "brand.raw": {
        "value": "Cetaphil"
      }
    }
  }
}

Cạm bẫy chí mạng (Nhắc lại Bài 17): Nếu bạn dùng term trên một trường kiểu text, bạn sẽ gần như 100% nhận về kết quả rỗng. Ví dụ: Trường name đang lưu chuỗi "Sữa rửa mặt Cetaphil". Analyzer đã băm nó thành các chữ thường ["sữa", "rửa", "mặt", "cetaphil"]. Nếu bạn chạy term với giá trị "Sữa rửa mặt Cetaphil", Elasticsearch sẽ đi tìm token dài ngoằng có chứa chữ hoa đó trong Index, và kết quả dĩ nhiên là 0 vì token đó không hề tồn tại. Quy tắc: Chỉ dùng term cho trường keyword.

2. terms Query: Tìm kiếm danh sách giá trị (Giống IN của SQL)

Khi giao diện của Hasaki cho phép khách hàng tick chọn nhiều thương hiệu cùng lúc (Ví dụ: Lọc ra các sản phẩm thuộc hãng L'Oreal HOẶC Cetaphil), bạn sẽ cần mệnh đề IN của SQL. Elasticsearch cung cấp terms.

Cú pháp:

JSON

GET products/_search
{
  "query": {
    "terms": {
      "brand.raw": [
        "L'Oreal", 
        "Cetaphil", 
        "Vichy"
      ]
    }
  }
}

Hiệu năng: terms query cực kỳ tối ưu vì nó thực hiện nhiều phép tra cứu (lookup) song song trên Inverted Index.

3. range Query: Tìm kiếm trong khoảng

Bất kỳ hệ thống E-commerce nào cũng có bộ lọc giá tiền và ngày tháng. range query là công cụ chuyên dụng cho việc này.

Cú pháp:

JSON

GET products/_search
{
  "query": {
    "range": {
      "price": {
        "gte": 150000, 
        "lte": 500000 
      }
    }
  }
}

(Ghi chú: gte = Greater than or equal (>=), lte = Less than or equal (<=), gt = Greater than (>), lt = Less than (<).

Tính năng đặc biệt cho Date: Trường Date trong Elasticsearch cực kỳ mạnh mẽ với phép tính toán thời gian (Date Math). Bạn có thể lọc động dựa vào thời điểm hiện tại (now):

JSON

"range": {
  "created_at": {
    "gte": "now-7d/d", // Từ 7 ngày trước (làm tròn xuống đầu ngày)
    "lte": "now"       // Tới thời điểm hiện tại
  }
}

(Chi tiết này giúp code Backend Golang/PHP của bạn cực kỳ nhàn rỗi, không cần phải tự khởi tạo biến $sevenDaysAgo rườm rà rồi truyền vào nữa).

4. exists Query: Kiểm tra trường có tồn tại (Not Null)

Trong SQL, bạn thường phải check WHERE discount IS NOT NULL. Elasticsearch không lưu giá trị null vào Inverted Index. Nếu một Document có "discount": null, trường đó coi như không tồn tại trong Index.

Để lấy ra những sản phẩm có lưu thông tin giảm giá, ta dùng exists:

JSON

GET products/_search
{
  "query": {
    "exists": {
      "field": "discount"
    }
  }
}

Thế làm sao để tìm IS NULL? Elasticsearch đã loại bỏ câu query missing ở các phiên bản cũ. Để tìm IS NULL, bạn phải đặt câu lệnh exists vào bên trong block must_not của mệnh đề bool (Đã học ở Bài 23): "Tìm tất cả những Document KHÔNG THỎA MÃN điều kiện exists".

Tóm lại, Term-level queries là những câu lệnh truy vấn mang tính máy móc (nhị phân): "Có" hoặc "Không có". Chúng không phán đoán độ liên quan (Relevance Score), vì thế chúng thường xuyên được đẩy vào trong khối filter context để tận dụng khả năng caching cực mạnh của Elasticsearch.

Tuy nhiên, E-commerce không chỉ có filter giá hay lọc trạng thái. Khi khách hàng lên thanh công cụ gõ "Srm trị mụn Cetaphil", họ không thể gõ chính xác 100% tên sản phẩm. Đó là lúc chúng ta phải triệu hồi sức mạnh phức tạp và tốn CPU nhất của Elasticsearch: Full-text Queries.


All Rights Reserved

Viblo
Let's register a Viblo Account to get more interesting posts.