Elasticsearch là gì?
Bài đăng này đã không được cập nhật trong 4 năm
1. Mở đầu
Xin chào các bạn, hôm nay mình sẽ giới thiệu một công nghệ search khá hay ho và phổ biến đó là elasticsearch. Trong bài viết này, chúng ta sẽ cùng tìm hiểu các khái niệm, cài đặt, các API & hoạt động của kỹ thuật search này.
2. Giới thiệu elasticsearch
Nói qua một chút cơ bản về elasticsearch, thì elasticsearch là một công nghệ mã nguồn mở, nó giúp chúng ta tạo ra các server có chức năng hỗ trợ tìm kiếm toàn văn.
Elasticsearch là một công cụ tìm kiếm dựa trên phần mềm Lucene. Nó cung cấp một bộ máy tìm kiếm dạng phân tán, có đầy đủ công cụ với một giao diện web HTTP có hỗ trợ dữ liệu JSON. Elasticsearch được phát triển bằng Java và được phát hành dạng nguồn mở theo giấy phép Apache.
3. Cài đặt
Có rất nhiều cách để cài đặt Elasticsearch, các bạn có thể tham khảo tài liệu cài đặt trên trang chủ Elasticsearch ở đây.
Trong bài viết này, mình sẽ chọn cách cài đặt bằng docker.
Mình thường chọn cách cài đặt bằng docker vì bằng cách này, mình có thể chủ động bật/tắt server nếu k cần thiết. Trong trường hợp có nhiều dự án thì cũng có thể tạo ra các container elasticsearch khác nhau để làm việc với các server độc lập. Thêm nữa, nó giúp mình tránh được nhiều lỗi khi quá trình cài đặt truyền thống có vấn đề (máy thiếu thư viện, package liên quan ...)
Bằng cách này, chỉ cần có chút kiến thức về docker, chúng ta có thể setup được một cách dễ dàng. Đầu tiên pull image của elasticsearch về bằng lệnh:
docker pull docker.elastic.co/elasticsearch/elasticsearch:7.9.2
Sau khi pull thành công elasticsearch image, chúng ta có thể start elasticsearch server bằng docker container bằng lệnh:
docker run -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" docker.elastic.co/elasticsearch/elasticsearch:7.9.2
Sau khi start 1 Elasticsearch server bằng docker thành công, lúc này, container sẽ bind 2 port tương ứng là 9200 & 9300 ra máy local.
Port 9200 sẽ được sử dụng cho tất cả các API thông qua giao thức HTTP, còn port 9300 là một giao thức binary tùy chỉnh được sử dụng để liên lạc giữa các nodes trong một cluster.
Chúng ta có thể truy cập vào địa chỉ http://localhost:9200 trên trình duyệt để xem được thông tin về Elasticsearch server.
4. Các khái niệm
Trong phần tiếp theo, chúng ta sẽ cùng tìm hiểu về một số khái niệm của Elasticsearch
Node
Node là một server đơn lẻ, là một phần của cluster, lưu trữ data của bạn, tham gia vào chức năng lập chỉ mục và tìm kiếm.
Cluster
Cluster là 1 tập hợp các kết nối của các node trong Elasticsearch, Nếu bạn start 1 node đơn lẻ (single node) như câu lệnh start Elasticsearch container ở trên thì bạn đã có 1 cluster có 1 node trong đó.
Index
Index là một tập hợp của các document mà chứa những đặc điểm tương tự. Index cũng được định danh bằng tên, tên này được sử dụng khi thực hiện các hoạt động như thêm, sửa, xóa hay update các document trong đó.
Document
Document là đơn vị cơ bản của thông tin, cần phải được đánh index. Với mỗi loại index, bạn có thể có vô số document trong đó.
5. Elasticseach API
Tiếp theo, chúng ta sẽ cùng nhau tìm hiểu các API cơ bản của elasticsearch.
5.1. Kiểm tra trạng thái
Đầu tiên, chúng ta cùng kiểm tra trạng thái của elasticsearch server bằng API sau:
GET http://localhost:9200/_cat/health
sử dụng lệnh curl
để kiểm tra như sau:
~$ curl -X GET http://localhost:9200/_cat/health
1603283841 12:37:21 docker-cluster green 1 1 0 0 0 0 0 0 - 100.0%
Trạng thái hiển thị status green
tức là elasticsearch server của chúng ta đang hoạt động bình thường.
5.2. Các API index
Trong Elasticsearch thì index có vai trò như bảng CSDL ở trong SQL, nó là 1 tập hợp các dữ liệu mà từ đây chúng ta có thể truy vấn tìm những thông tin mong muốn. Về mặt bản chất ở đây, Elasticsearch hoạt động dựa trên việc chúng ta tổ chức và put dữ liệu vào theo các index và từ đó Elasticsearch sẽ hỗ trợ chúng ta truy vấn & tìm kiếm dựa trên những data đó
Get index
Đầu tiên chúng ta kiểm tra các index bằng API sau
GET http://localhost:9200/_cat/indices
Đầu tiên có thể server hiện đang chưa có index nào, không sao, chúng ta tiếp tục đến với API tạo index và sẽ kiểm tra lại sau.
Create index
Tạo 1 index product bằng API sau:
PUT http://localhost:9200/product?pretty
Lệnh curl:
~$ curl -X PUT http://localhost:9200/product?pretty
{
"acknowledged" : true,
"shards_acknowledged" : true,
"index" : "product"
}
Response trả về kết quả như trên có nghĩa là đã tạo thành công index product. Tham số pretty
để output hiển thị ra kết quả pretty JSON để dễ dàng kiểm tra hơn
Bây giờ, hãy cùng quay lại kiểm tra API get index bên trên:
~$ curl -X GET http://localhost:9200/_cat/indices?v
health status index uuid pri rep docs.count docs.deleted store.size pri.store.size
yellow open product _g763PiKRceBeVtZ8bUw2A 1 1 0 0 208b 208b
Như vậy chúng ta đã thấy thông tin 1 index vừa được tạo ra. Tham số ?v
để hiển thị ra title giúp việc checking dễ dàng hơn.
Delete index
Xóa index bằng API sau
DELETE http://localhost:9200/product?pretty
Thực hiện lệnh curl:
~$ curl -X DELETE http://localhost:9200/product?pretty
{
"acknowledged" : true
}
Kết quả hiển thị như trên tức là đã xóa thành công index product
5.3. Các API document
Trong phần tiếp theo, chúng ta sẽ cùng xem việc thao tác với dữ liệu trên các index (đó là các document) như thế nào? Các API CRUD document & truy vấn thông tin document như thế nào?
Đầu tiên hãy cùng tạo mới index book bằng lệnh sau:
curl -X PUT http://localhost:9200/book?pretty
Create document
Tiến hành tạo mới 1 document trong index bằng API sau:
POST http://localhost:9200/{index}/_doc/{document_id}
<{document request body}>
Ví dụ tạo mới 1 document trong index book với id = 1 bằng lệnh sau
curl -X PUT http://localhost:9200/book/_doc/1 -H 'Content-Type: application/json' -d'
{
"name": "Math",
"price": 111,
"author": {
"name": "John",
"age": 55
}
}
'
Thông thường, chúng ta sẽ phải chỉ định rõ id của document, trong trường hợp không truyền lên tham số document_id
thì server sẽ tự động tạo ra 1 id cho document đó.
Update document
Tương tự API create document ở trên, API update document bằng cách sử dụng method PUT.
PUT http://localhost:9200/{index}/_doc/{document_id}
<{document request body}>
Việc update thì chúng ta buộc lòng phải chỉ định id của document đó.
Get document by ID
Thực hiện tìm kiếm thông tin document theo id = API sau:
GET http://localhost:9200/{index}/_doc/{document_id}?pretty
Ví dụ, sử dụng curl để tìm kiếm document trong index book có id = 1 đã tạo ở trên:
~$ curl -X GET http://localhost:9200/book/_doc/1?pretty
{
"_index" : "book",
"_type" : "_doc",
"_id" : "1",
"_version" : 3,
"_seq_no" : 3,
"_primary_term" : 1,
"found" : true,
"_source" : {
"name" : "Math",
"price" : 111,
"author" : {
"name" : "John",
"age" : 55
}
}
}
Chúng ta có thể kiểm tra thông tin document ở phần _source
của output.
Show all document
Bên cạnh đó, ta cũng có thể tiến hành kiểm tra tất cả các document bằng lệnh sau:
curl -X GET http://localhost:9200/book/_search?pretty
Delete document
Thực hiện xóa document bằng API
DELETE http://localhost:9200/{index}/_doc/{document_id}
5.4. Truy vấn trên Elasticsearch
Đến đây, chúng ta đã nắm được các khái niệm và một số API cơ bản để thao tác với document & index trong Elasticsearch
Trong phần tiếp theo này, chúng ta cùng tìm hiểu về tính năng rất quan trọng của Elasticsearch đó là một số cách truy vấn để làm sao có thể lấy được data theo ý muốn trong Elasticsearch
Trong Elasticsearch có rất nhiều kỹ thuật truy vấn để lấy ra được các data mong muốn, nhưng trong phần này mình chỉ đề cập đến một số truy vấn cơ bản, giúp các bạn có thể hiểu, vận dụng và từ đó tìm hiểu thếm các truy vấn khác
Trước tiên, để dễ hình dung cho ví dụ truy vấn này chúng ta cần chuẩn bị 1 tập dữ liệu mẫu. Trong ví dụ này mình sẽ sử dụng dữ liệu mẫu elasticoffee-data trên Github repo elastic/examples.
Cụ thể, mình sẽ insert 20 bản ghi trong example data trên vào index elasticoffee
bằng lệnh sau:
curl -X POST http://localhost:9200/elasticoffee/_bulk?pretty -H 'Content-Type: application/x-ndjson' -d '
{ "index" : { "_index" : "elasticoffee", "_type" : "doc", "_id" : "1" } }
{"sceneID": "2", "sceneData": "0", "entityID": "zwave.quad2", "quadId": 2, "quadMod": "1", "@timestamp": "2018-02-27T22:26:39Z", "beverageClass": "Hot Beverages", "beverage": "Latte", "beverageSide": "left", "beverageIndex": 5, "quantity": 1}
{ "index" : { "_index" : "elasticoffee", "_type" : "doc", "_id" : "2" } }
{"sceneID": "3", "sceneData": "0", "entityID": "zwave.quad1", "quadId": 1, "quadMod": "0", "@timestamp": "2018-02-27T22:26:39Z", "beverageClass": "Hot Beverages", "beverage": "Mocha", "beverageSide": "left", "beverageIndex": 2, "quantity": 1}
{ "index" : { "_index" : "elasticoffee", "_type" : "doc", "_id" : "3" } }
{"sceneID": "1", "sceneData": "0", "entityID": "zwave.quad2", "quadId": 2, "quadMod": "1", "@timestamp": "2018-02-27T22:26:39Z", "beverageClass": "Hot Beverages", "beverage": "Espresso", "beverageSide": "left", "beverageIndex": 4, "quantity": 1}
{ "index" : { "_index" : "elasticoffee", "_type" : "doc", "_id" : "4" } }
{"sceneID": "2", "sceneData": "0", "entityID": "zwave.quad1", "quadId": 1, "quadMod": "0", "@timestamp": "2018-02-28T15:29:39Z", "beverageClass": "Hot Beverages", "beverage": "Americano", "beverageSide": "left", "beverageIndex": 1, "quantity": 1}
{ "index" : { "_index" : "elasticoffee", "_type" : "doc", "_id" : "5" } }
{"sceneID": "1", "sceneData": "0", "entityID": "zwave.quad1", "quadId": 1, "quadMod": "0", "@timestamp": "2018-02-28T15:29:40Z", "beverageClass": "Hot Beverages", "beverage": "Cappuccino", "beverageSide": "left", "beverageIndex": 0, "quantity": 1}
{ "index" : { "_index" : "elasticoffee", "_type" : "doc", "_id" : "6" } }
{"sceneID": "3", "sceneData": "0", "entityID": "zwave.quad1", "quadId": 1, "quadMod": "0", "@timestamp": "2018-02-28T15:29:40Z", "beverageClass": "Hot Beverages", "beverage": "Mocha", "beverageSide": "left", "beverageIndex": 2, "quantity": 1}
{ "index" : { "_index" : "elasticoffee", "_type" : "doc", "_id" : "7" } }
{"sceneID": "3", "sceneData": "0", "entityID": "zwave.quad4", "quadId": 4, "quadMod": "1", "@timestamp": "2018-02-28T15:36:24Z", "beverageClass": "Hot Beverages", "beverage": "Coffee", "beverageSide": "right", "beverageIndex": 6, "quantity": 1}
{ "index" : { "_index" : "elasticoffee", "_type" : "doc", "_id" : "8" } }
{"sceneID": "1", "sceneData": "0", "entityID": "zwave.quad4", "quadId": 4, "quadMod": "1", "@timestamp": "2018-02-28T15:36:24Z", "beverageClass": "Hot Beverages", "beverage": "Espresso", "beverageSide": "right", "beverageIndex": 4, "quantity": 1}
{ "index" : { "_index" : "elasticoffee", "_type" : "doc", "_id" : "9" } }
{"sceneID": "2", "sceneData": "0", "entityID": "zwave.quad4", "quadId": 4, "quadMod": "1", "@timestamp": "2018-02-28T15:36:25Z", "beverageClass": "Hot Beverages", "beverage": "Latte", "beverageSide": "right", "beverageIndex": 5, "quantity": 1}
{ "index" : { "_index" : "elasticoffee", "_type" : "doc", "_id" : "10" } }
{"sceneID": "1", "sceneData": "0", "entityID": "zwave.quad3", "quadId": 3, "quadMod": "0", "@timestamp": "2018-02-28T15:36:26Z", "beverageClass": "Hot Beverages", "beverage": "Cappuccino", "beverageSide": "right", "beverageIndex": 0, "quantity": 1}
{ "index" : { "_index" : "elasticoffee", "_type" : "doc", "_id" : "11" } }
{"sceneID": "2", "sceneData": "0", "entityID": "zwave.quad3", "quadId": 3, "quadMod": "0", "@timestamp": "2018-02-28T15:36:26Z", "beverageClass": "Hot Beverages", "beverage": "Americano", "beverageSide": "right", "beverageIndex": 1, "quantity": 1}
{ "index" : { "_index" : "elasticoffee", "_type" : "doc", "_id" : "12" } }
{"sceneID": "4", "sceneData": "0", "entityID": "zwave.quad3", "quadId": 3, "quadMod": "0", "@timestamp": "2018-02-28T15:36:25Z", "beverageClass": "Hot Beverages", "beverage": "Macchiato", "beverageSide": "right", "beverageIndex": 3, "quantity": 1}
{ "index" : { "_index" : "elasticoffee", "_type" : "doc", "_id" : "13" } }
{"sceneID": "3", "sceneData": "0", "entityID": "zwave.quad3", "quadId": 3, "quadMod": "0", "@timestamp": "2018-02-28T15:36:25Z", "beverageClass": "Hot Beverages", "beverage": "Mocha", "beverageSide": "right", "beverageIndex": 2, "quantity": 1}
{ "index" : { "_index" : "elasticoffee", "_type" : "doc", "_id" : "14" } }
{"sceneID": "3", "sceneData": "0", "entityID": "zwave.quad4", "quadId": 4, "quadMod": "1", "@timestamp": "2018-02-28T15:34:38Z", "beverageClass": "Hot Beverages", "beverage": "Coffee", "beverageSide": "right", "beverageIndex": 6, "quantity": 1}
{ "index" : { "_index" : "elasticoffee", "_type" : "doc", "_id" : "15" } }
{"sceneID": "4", "sceneData": "0", "entityID": "zwave.quad4", "quadId": 4, "quadMod": "1", "@timestamp": "2018-02-28T15:36:23Z", "beverageClass": "Hot Beverages", "beverage": "Other", "beverageSide": "right", "beverageIndex": 7, "quantity": 1}
{ "index" : { "_index" : "elasticoffee", "_type" : "doc", "_id" : "16" } }
{"sceneID": "3", "sceneData": "0", "entityID": "zwave.quad2", "quadId": 2, "quadMod": "1", "@timestamp": "2018-02-27T22:26:40Z", "beverageClass": "Hot Beverages", "beverage": "Coffee", "beverageSide": "left", "beverageIndex": 6, "quantity": 1}
{ "index" : { "_index" : "elasticoffee", "_type" : "doc", "_id" : "17" } }
{"sceneID": "4", "sceneData": "0", "entityID": "zwave.quad2", "quadId": 2, "quadMod": "1", "@timestamp": "2018-02-27T22:26:42Z", "beverageClass": "Hot Beverages", "beverage": "Other", "beverageSide": "left", "beverageIndex": 7, "quantity": 1}
{ "index" : { "_index" : "elasticoffee", "_type" : "doc", "_id" : "18" } }
{"sceneID": "1", "sceneData": "0", "entityID": "zwave.quad3", "quadId": 3, "quadMod": "0", "@timestamp": "2018-02-28T16:46:05Z", "beverageClass": "Hot Beverages", "beverage": "Cappuccino", "beverageSide": "right", "beverageIndex": 0, "quantity": 1}
{ "index" : { "_index" : "elasticoffee", "_type" : "doc", "_id" : "19" } }
{"sceneID": "2", "sceneData": "0", "entityID": "zwave.quad3", "quadId": 3, "quadMod": "0", "@timestamp": "2018-02-28T16:46:39Z", "beverageClass": "Hot Beverages", "beverage": "Americano", "beverageSide": "right", "beverageIndex": 1, "quantity": 1}
{ "index" : { "_index" : "elasticoffee", "_type" : "doc", "_id" : "20" } }
{"sceneID": "1", "sceneData": "0", "entityID": "zwave.quad1", "quadId": 1, "quadMod": "0", "@timestamp": "2018-02-28T15:54:22Z", "beverageClass": "Hot Beverages", "beverage": "Cappuccino", "beverageSide": "left", "beverageIndex": 0, "quantity": 1}
'
Để truy vấn, chúng ta sẽ sử dụng API sau:
GET http://localhost:9200/elasticoffee/_search?pretty
<{request search body}>
Chúng ta sẽ thay đổi rquest body để truy vấn, mình sẽ đưa ra 1 vài ví dụ để dễ hình dung, các bạn nhớ chú ý đến phần request body nhé
Ví dụ 1 - Search tất cả các document, phân trang 2 document/page & bắt đầu từ document số 5
~$ curl -X GET 'http://localhost:9200/elasticoffee/_search?pretty' \
--header 'Content-Type: application/json' \
--data-raw '{
"query": {
"match_all": {}
},
"size": 2,
"from": 5
}
'
------ OUTPUT ----------------
{
"took" : 2,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 20,
"relation" : "eq"
},
"max_score" : 1.0,
"hits" : [
{
"_index" : "elasticoffee",
"_type" : "doc",
"_id" : "6",
"_score" : 1.0,
"_source" : {
"sceneID" : "3",
"sceneData" : "0",
"entityID" : "zwave.quad1",
"quadId" : 1,
"quadMod" : "0",
"@timestamp" : "2018-02-28T15:29:40Z",
"beverageClass" : "Hot Beverages",
"beverage" : "Mocha",
"beverageSide" : "left",
"beverageIndex" : 2,
"quantity" : 1
}
},
{
"_index" : "elasticoffee",
"_type" : "doc",
"_id" : "7",
"_score" : 1.0,
"_source" : {
"sceneID" : "3",
"sceneData" : "0",
"entityID" : "zwave.quad4",
"quadId" : 4,
"quadMod" : "1",
"@timestamp" : "2018-02-28T15:36:24Z",
"beverageClass" : "Hot Beverages",
"beverage" : "Coffee",
"beverageSide" : "right",
"beverageIndex" : 6,
"quantity" : 1
}
}
]
}
}
Response nhận được 2 document với id là 6, 7
Ví dụ 2 - Search tất cả các document, phân trang 2 document/page sort theo beverageIndex DESC
curl -X GET 'http://localhost:9200/elasticoffee/_search?pretty' \
--header 'Content-Type: application/json' \
--data-raw '{
"query": {
"match_all": {}
},
"sort": [
{
"beverageIndex": {
"order": "desc"
}
}
],
"size": 2
}
'
------------- OUTPUT ---------------
{
"took" : 2,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 20,
"relation" : "eq"
},
"max_score" : null,
"hits" : [
{
"_index" : "elasticoffee",
"_type" : "doc",
"_id" : "15",
"_score" : null,
"_source" : {
"sceneID" : "4",
"sceneData" : "0",
"entityID" : "zwave.quad4",
"quadId" : 4,
"quadMod" : "1",
"@timestamp" : "2018-02-28T15:36:23Z",
"beverageClass" : "Hot Beverages",
"beverage" : "Other",
"beverageSide" : "right",
"beverageIndex" : 7,
"quantity" : 1
},
"sort" : [
7
]
},
{
"_index" : "elasticoffee",
"_type" : "doc",
"_id" : "17",
"_score" : null,
"_source" : {
"sceneID" : "4",
"sceneData" : "0",
"entityID" : "zwave.quad2",
"quadId" : 2,
"quadMod" : "1",
"@timestamp" : "2018-02-27T22:26:42Z",
"beverageClass" : "Hot Beverages",
"beverage" : "Other",
"beverageSide" : "left",
"beverageIndex" : 7,
"quantity" : 1
},
"sort" : [
7
]
}
]
}
}
=> Response hiển thị với 2 document có id = 15 & 17 có beverageIndex cao nhất.
Ví dụ 3 - Search tất cả các document, phân trang 2 document/page với điều kiện entityID = "zwave.quad4"
curl -X GET 'http://localhost:9200/elasticoffee/_search?pretty' \
--header 'Content-Type: application/json' \
--data-raw '{
"query": {
"match": {
"entityID": "zwave.quad4"
}
},
"size": 2
}'
------------- OUTPUT ---------------
{
"took" : 2,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 5,
"relation" : "eq"
},
"max_score" : 1.3397743,
"hits" : [
{
"_index" : "elasticoffee",
"_type" : "doc",
"_id" : "7",
"_score" : 1.3397743,
"_source" : {
"sceneID" : "3",
"sceneData" : "0",
"entityID" : "zwave.quad4",
"quadId" : 4,
"quadMod" : "1",
"@timestamp" : "2018-02-28T15:36:24Z",
"beverageClass" : "Hot Beverages",
"beverage" : "Coffee",
"beverageSide" : "right",
"beverageIndex" : 6,
"quantity" : 1
}
},
{
"_index" : "elasticoffee",
"_type" : "doc",
"_id" : "8",
"_score" : 1.3397743,
"_source" : {
"sceneID" : "1",
"sceneData" : "0",
"entityID" : "zwave.quad4",
"quadId" : 4,
"quadMod" : "1",
"@timestamp" : "2018-02-28T15:36:24Z",
"beverageClass" : "Hot Beverages",
"beverage" : "Espresso",
"beverageSide" : "right",
"beverageIndex" : 4,
"quantity" : 1
}
}
]
}
}
=> Response trả về 2 document có id = 7, 8 có giá trị entityID
= "zwave.quad4"
Ví dụ 4 - Search các document có điều kiện entityID = "zwave.quad4" & beverageIndex = "5"
=> Sử dụng truy vấn bool.must
:
curl -X GET 'http://localhost:9200/elasticoffee/_search?pretty' \
--header 'Content-Type: application/json' \
--data-raw '{
"query": {
"bool": {
"must": [
{
"match": {
"entityID": "zwave.quad4"
}
},
{
"match": {
"beverageIndex": "5"
}
}
]
}
}
}'
=> Response sẽ trả về kết quả document có id =9 thỏa mãn cả 2 điều kiện entityID = "zwave.quad4" & beverageIndex = "5"
Ví dụ 5 - Search các document có điều kiện entityID = "zwave.quad4" hoặc beverageIndex = "5"
=> Sử dụng truy vấn bool.should
:
curl -X GET 'http://localhost:9200/elasticoffee/_search?pretty' \
--header 'Content-Type: application/json' \
--data-raw '{
"query": {
"bool": {
"should": [
{
"match": {
"entityID": "zwave.quad4"
}
},
{
"match": {
"beverageIndex": "5"
}
}
]
}
}
}'
=> Response trả về các document có id = 9, 7, 8, 14, 15, 1 có 1 trong 2 điều kiện thỏa mãn entityID = "zwave.quad4" hoặc beverageIndex = "5"
6. Kết luận
Như vậy, qua bài viết này mình đã giới thiệu qua về Elasticsearch, cách cài đặt cũng như sử dụng một số API cơ bản của kỹ thuật search này. Ngoài những truy vấn cơ bản mình đưa ra trong ví dụ trên, Elasticsearch vẫn còn rất nhiều loại truy vấn khác, các bạn có thể tham khảo thêm tài liệu trên trang chủ Elasticsearch ở đây. Hy vọng bài viết này sẽ giúp ích cho các bạn trong học tập cũng như công việc, cảm ơn các bạn đã chú ý theo dõi.
All rights reserved