+1

Elasticsearch là gì?

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

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí