Trong thời đại dữ liệu lớn, việc tìm kiếm và phân tích dữ liệu một cách hiệu quả trở nên vô cùng quan trọng. Elasticsearch, với khả năng tìm kiếm mạnh mẽ và linh hoạt, đã trở thành một công cụ không thể thiếu trong nhiều dự án. Để tiếp nối bài viết Tìm hiểu cơ bản về Elasticsearch, cài đặt Elasticsearch và Kibana trong CentOS, bài viết này sẽ giới thiệu đến bạn một số câu truy vấn trong Elasticsearch, giúp bạn hiểu rõ hơn về cách xây dựng và tối ưu hóa các truy vấn để khai thác dữ liệu một cách tối ưu nhất
Nạp dữ liệu mẫu
Để thực hành Elasticsearch cung cập một tập dữ liệu mẫu, gồm 1000 bản ghi lưu trữ thông tin tài khoản bank, ta sẽ nạp dữ liệu này vào Elasticsearch để thực hành. Mỗi dữ liệu Document có cấu trúc dạng:
{
"account_number": 0,
"balance": 16623,
"firstname": "Bradshaw",
"lastname": "Mckenzie",
"age": 29,
"gender": "F",
"address": "244 Columbus Place",
"employer": "Euron",
"email": "bradshawmckenzie@euron.com",
"city": "Hobucken",
"state": "CO"
}
Trước tiên tải về file JSON chứa 1000 bản ghi dữ liệu này tại: Tải về JSON Data Bank, lưu nó thành file accounts.json, rồi gõ lệnh sau để nạp nó vào index bank
curl -H "Content-Type: application/json" -XPOST "ip_may_ao:9200/bank/_bulk?pretty&refresh" --data-binary "@accounts.json"
Giờ bạn đang có Index tên bank chứa 1000 Document với cấu trúc mỗi Document như trên.
Có thể thử kiểm tra một Document, ví dụ kiểm tra id = 3
GET /bank/_doc/3?pretty
{
"_index" : "bank",
"_type" : "_doc",
"_id" : "3",
"_version" : 1,
"_seq_no" : 800,
"_primary_term" : 1,
"found" : true,
"_source" : {
"account_number" : 3,
"balance" : 44947,
"firstname" : "Levine",
"lastname" : "Burks",
"age" : 26,
"gender" : "F",
"address" : "328 Wilson Avenue",
"employer" : "Amtap",
"email" : "levineburks@amtap.com",
"city" : "Cochranville",
"state" : "HI"
}
}
Truy vấn đơn giản đến Elesticsearch
Tìm tất cả các Document có trong index /bank/
GET /bank/_search
{
"query": { "match_all": {} }
}
Kết quả có dạng
{
"took": 31,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 1000,
"relation": "eq"
},
"max_score": 1,
"hits": [
{
"_index": "bank",
"_id": "1",
"_score": 1,
"_source": {
"account_number": 1,
"balance": 39225,
"firstname": "Amber",
"lastname": "Duke",
"age": 32,
"gender": "M",
"address": "880 Holmes Lane",
"employer": "Pyrami",
"email": "amberduke@pyrami.com",
"city": "Brogan",
"state": "IL"
}
},
...
]
}
}
Giải thích :
- took – thời gian (mili giây) hoàn thành truy vấn
- timed_out - cho biết vượt thời gian (thời gian hoàn thành vượt ngưỡng bị dừng) hay không
- _shards - cho biết tìm trên bao nhiêu shard (phân đoạn index)
- hits - kết quả tìm kiếm
- hits.total - tổng số kết quả tìm được
- hits.hits - mảng dữ liệu thực sự trả về (mặc định 10 document đầu tiên)
Thêm size để giới hạn số kết quả trả về (mặc định nếu không chỉ ra nó sẽ trả về tối đa 10)
GET /bank/_search
{
"query": {
"match_all": {}
},
"size": 2
}
Chỉ ra dữ liệu trả về bắt đầu từ phần tử nào với tham số from
GET /bank/_search
{
"query": {
"match_all": {}
},
"from": 10,
"size": 10
}
Sắp xếp kết quả trả về (Ví dụ các dữ liệu sắp xếp giảm dần theo trường dữ liệu balance)
GET /bank/_search
{
"query": { "match_all": {} },
"size": 3,
"sort": { "balance": { "order": "desc" } }
}
Thực hiện tìm kiếm nâng cao với Elasticsearch
Giới hạn lấy những trường dữ liệu cụ thể nào đó thôi thì dùng tham số _source với mảng liệt kê các trường dữ liệu muốn này. Ví dụ chỉ lấy các dữ liệu account_number và balance của bank
GET /bank/_search
{
"query": { "match_all": {} },
"_source": ["account_number", "balance"]
}
Ở các ví dụ trước, sử dụng match_all ở query có nghĩa là trả về toàn bộ Document có trong Index. Giờ đến lúc sẽ thực hiện tìm kiếm, sẽ sử dụng dến match, giả sử tìm các tài khoản bank có account_number bằng 20, sẽ viết truy vấn như sau:
GET /bank/_search
{
"query": { "match": { "account_number": 20 } }
}
Tương tự, nếu muốn tìm các tài khoản mà địa chỉ address có chứa mill HOẶC lane
GET /bank/_search
{
"query": { "match": { "address": "mill lane" } }
}
Nếu muốn trả về address phải có cả cả cụm từ mill lane thì cần đến match_phrase
GET /bank/_search
{
"query": { "match_phrase": { "address": "mill lane" } }
}
Sử dụng điều kiện logic bool trong truy vấn tìm kiếm
Sử đụng điều kiện must kết quả trả về khi tất cả các truy vấn là đúng, ví dụ sau tìm tất cả các địa chỉ có chứa từ mill VÀ lane
GET /bank/_search
{
"query": {
"bool": {
"must": [
{ "match": { "address": "mill" } },
{ "match": { "address": "lane" } }
]
}
}
}
Sử đụng điều kiện should nó tương tự như phép logic HOẶC
GET /bank/_search
{
"query": {
"bool": {
"should": [
{ "match": { "address": "mill" } },
{ "match": { "address": "lane" } }
]
}
}
}
Sử đụng điều kiện must_not tương tự như phép logic PHỦ ĐỊNH
GET /bank/_search
{
"query": {
"bool": {
"must_not": [
{ "match": { "address": "mill" } },
{ "match": { "address": "lane" } }
]
}
}
}
Kết hợp nhiều điều kiện must, must_not, should vào truy vấn
{
"query": {
"bool": {
"must": [
{ "term": { "gender": "F" } },
{ "range": { "balance": { "gte": 10000 } } }
],
"must_not": [
{ "term": { "state": "CA" } }
],
"should": [
{ "term": { "city": "Hobucken" } },
{ "range": { "age": { "gte": 25, "lte": 35 } } }
]
}
}
}
Lọc kết quả Elasticsearch
Để lọc dùng đến filter, ví dụ sử dụng loại range để lọc lấy lấy dữ liệu balance trong khoảng nào đó.
GET /bank/_search
{
"query": {
"bool": {
"must": { "match_all": {} },
"filter": {
"range": {
"balance": {
"gte": 20000,
"lte": 30000
}
}
}
}
}
}
Trong bài viết này, chúng ta đã tìm hiểu về một số câu truy vấn trong Elasticsearch. Việc nắm vững cách sử dụng các câu truy vấn này sẽ giúp bạn khai thác tối đa sức mạnh của Elasticsearch, từ việc tìm kiếm dữ liệu chính xác đến các tìm kiếm phức tạp và linh hoạt hơn. Ngoài ra còn nhiều loại cú pháp tạo query tìm kiếm khác như wildcard, regexp, term, fuzzy, query_string..., bạn có thể tham khảo tại https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl.html .