+7

Query DSL trong Elasticsearch

Các bài viết về Elasticseach đã có nhiều trên Viblo, từ khái quát đến cụ thể cách hoạt động. Các bạn có thể tìm đọc cái bài viết của các tác giả dinhhoanglong91Ngoc Nguyen. Còn trong bài viết này, tôi xin phép trình bày một số query DSL mà tôi đã từng sử dụng.

1. Query DSL (domain-specific language)

Elasticsearch cung cấp full Query DSL dựa trên JSON để định nghĩa truy vấn. Có 2 loại:

- Câu truy vấn đơn:

Câu truy vấn đơn tìm kiếm một giá trị cụ thể trong một field cụ thể. Gồm các câu: match, term, range.

- Câu truy vấn kép:

Câu truy vấn kép bao gồm nhiều câu truy vấn đơn cùng các truy vấn kép, được sử dụng kết hợp theo một logic hợp lý. Ví dụ: bool, dis_max.

2. Match All Query

Câu truy vấn đơn giản nhất, phù hợp với tất cả các tài liệu.

GET resumes_development/_search
{
    "query": {
        "match_all": {}
    }
}

Response:

{
  "took": 4,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "failed": 0
  },
  "hits": {
    "total": 1012,
    "max_score": 1,
    "hits": [
       ...   
    ]
  }
}

3. Full text queries

Loại truy vấn full text cấp cao này thường được sử dụng cho các trường full text như nội dung email. Các trường này thường được phân tích từ trước, và có các loại phân tích (analyzer) cho mỗi loại field.

- Match query

Truy vấn chuẩn để thực hiện full text query. Bao gồm truy vấn kết hợp và truy vấn cụm từ hoặc gần đúng. Match query chấp nhận văn bản, số, ngày tháng.

GET resumes_development/_search
{
    "query": {
        "match" : {
            "name" : "Phong Test"
        }
    }
}
"hits": {
    "total": 273,
    "max_score": 2.6868117,
    ...
}

Kết quả trả về là tất cả các record mà trong tên có Phong hoặc Test.

Ta cũng có thể thêm điều kiện là "and" đối với query (mặc định là or):

GET resumes_development/_search
{
    "query": {
        "match" : {
            "name" : {
                "query" : "Phong Test",
                "operator" : "and"
            }
        }
    }
}
"hits": {
    "total": 239,
    "max_score": 2.6868117,
    ...
}

Khi này trong kết quả trả về phải có cả PhongTest.

- Match Phrase Prefix Query

Truy vấn match_phrase phân tích văn bản và tạo 1 truy vấn cụm từ.

GET resumes_development/_search
{
    "query": {
        "match_phrase" : {
            "name" : "Phong Henry"
        }
    }
}

Câu truy vấn này sẽ trả về các record mà trong name có cụm từ Phong Henry

* Match Phrase Prefix Query

Cũng giống match_phrase, nhưng thêm điều kiện khớp với tiền tố của từ trong văn bản.

GET resumes_development/_search
{
    "query": {
        "match_phrase_prefix" : {
            "name" : "Phong Hen"
        }
    }
}

Với truy vấn này thì "Phong Henry" cũng match mà "Phong Henri" cũng đúng.

- Multi Match Query

Sử dụng từ truy vấn match và cho phép search nhiều trường:

GET resumes_development/_search
{
  "query": {
    "multi_match" : {
      "query":    "Nam", 
      "fields": [ "name", "address" ] 
    }
  }
}
  • Field có thể chỉ định bằng ký tự đại diện
GET resumes_development/_search
{
  "query": {
    "multi_match" : {
      "query":    "Nam", 
      "fields": [ "*_name", "address" ] 
    }
  }
}

Khi này ta có thể search cả fiel first_namelast_name

4. Term level queries

Truy vấn này thường được sử dụng cho các dữ liệu kiểu số, ngày tháng, enum. Ngoài ra cho phép bạn tạo truy vấn cấp thấp, bỏ qua bước phân tích.

- Term Query

Truy vấn term tìm những record có chứa cụm từ chính xác trong query.

GET resumes_development/_search
{
  "query": {
    "term" : { "name" : "test test test test" } 
  }
}

- Range Query

Trả về các record với trường khớp với phạm vi nhất định.

GET resumes_development/_search
{
    "query": {
        "range" : {
            "gpa" : {
                "gte" : 1,
                "lte" : 4
            }
        }
    }
}

Truy vấn range cho phép truyền vào các params:

  • gte: Lớn hơn hoặc bằng
  • gt: Lớn hơn
  • lte: Nhỏ hơn hoặc bằng
  • lt: Nhỏ hơn

Date format in range queries

GET resumes_development/_search
{
    "query": {
        "range" : {
            "apply_date" : {
                "gte": "01/01/2012",
                "lte": "2013",
                "format": "dd/MM/yyyy||yyyy"
            }
        }
    }
}

- Wildcard Query

Trả về các record khớp với các ký tự đại diện được đưa ra.

GET resumes_development/_search
{
    "query": {
        "wildcard" : { "name" : "*hon*" }
    }
}

Với query thế này thì record có name là "Phong" cũng đúng mà có name là "Thon" hày "Thonh" cũng đúng.

5. Bool Query

Cho phép kết hợp các câu truy vấn khác để tạo ra một logic hợp lý. Có các loại:

  • must: phải phù hợp với tất cả các điều kiện và đóng góp vào điểm số.
  • filter: giống với must nhưng bỏ qua điểm số. (Tham khảo)
  • should: Chỉ cần phù hợp vs một trong các điều kiện.
  • must_not: Người lại với must, phải không phù hợp với tất cả các điều kiện.
POST _search
{
  "query": {
    "bool" : {
      "must" : {
        "term" : { "user" : "kimchy" }
      },
      "filter": {
        "term" : { "tag" : "tech" }
      },
      "must_not" : {
        "range" : {
          "age" : { "gte" : 10, "lte" : 20 }
        }
      },
      "should" : [
        { "term" : { "tag" : "wow" } },
        { "term" : { "tag" : "elasticsearch" } }
      ],
      "minimum_should_match" : 1,
      "boost" : 1.0
    }
  }
}

Bool query in filter context

Nếu truy vấn sử dụng filter context và có mệnh đề should, thì trong đó phải tồn tại ít nhất một mệnh đề should là bắt buộc phù hợp.


All Rights Reserved

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