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ả dinhhoanglong91 và Ngoc 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. Elasticsearch cung cấp full ...
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ả dinhhoanglong91 và Ngoc 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.
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.
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": [ ... ] } }
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ả Phong và Test.
- 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_name và last_name
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.
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.