Trong bài viết này, tôi sẽ hướng dẫn các bạn 2 phần:
-
Cấu hình Elasticsearch
-
Tạo project với spring boot sử dụng thư viện spring data elasticsearch
Công cụ và thư viện được sử dụng trong bài viết:
- Spring tool suite 4
- Spring boot 2.7.3
- Spring data elasticsearch 4.4.2
- Maven 3
- Java 8
- Elasticsearh 8.4.1
- Elasticsearch 7.17.6
- Postman
- Elasticsearch head extension
1. Cài đặt Elasticsearch:
Đầu tiên các bạn truy cập đường dẫn bên dưới để tải về Elasticsearch mới nhất:
Link: https://www.elastic.co/downloads/elasticsearch
Nếu muốn tải về Elasticsearch phiên bản thấp hơn thì truy cập link bên dưới:
Link: https://www.elastic.co/downloads/past-releases
Trong bài viết này tôi tải về Elasticsearch zip file. Sau khi tải về tiến hành giải nén ta được thư mục như hình:
Cấu trúc thư mục:
Vào folder "config" và mở file "elasticsearch.yml":
Nội dung config file:
Thực sự không cần chỉnh sửa giá trị nào trong config file nhưng có 2 giá trị chúng ta cần quan tâm
-
cluster.name -> thiếp lập tên cho cluster. Tại đây tôi sẽ delete ký tự "#" và sửa tên thành "employee-cluster"
-
path.data -> thiếp lập đường dẫn lưu data. Tại đây tôi sẽ thiết lập lại đường dẫn thành "G:/elasticsearch-8.4.1/data"
Mặc định trong thư mục Elasticsearch vừa giải nén sẽ không có folder "data" nên tôi sẽ tự tạo 1 folder name là "data":
Tiếp theo để khởi động elasticsearch, tôi mở folder name là "bin" và run script file "elasticsearch.bat":
Sau khi khởi chạy thành công, truy cập đường dẫn "localhost:9200" để kiểm tra xem trạng thái Elasticsearch:
Như các bạn thấy, elasticsearch vẫn chưa hoạt động, check màn hình cmd thấy một vài lỗi về kết nối:
Lỗi này xảy ra trên phiên bản Elasticsearch 8 và để xử lý lỗi này, tôi sẽ mở file "elasticsearch.yml" trong folder "config" để sửa một vài thông tin:
Có 4 giá trị cần phải thay đổi, mặc định là "true" nên tôi sẽ chuyển thành "false":
-
xpack.security.enabled: true -> xpack.security.enabled: false
-
xpack.security.enrollment.enabled: true -> xpack.security.enrollment.enabled: false
-
xpack.security.http.ssl: enabled: true => xpack.security.http.ssl: enabled: false
-
xpack.security.transport.ssl: enabled: true => xpack.security.transport.ssl: enabled: false
Sau khi cập nhật lại 4 giá trị, vào folder "../bin" và khởi chạy script file "elasticsearch.bat":
Sau khi khởi chạy thành công, tiếp tục thử lại truy cập đường dẫn "localhost:9200":
Ta thấy elasticsearch đã khởi chạy thành công
Tiếp theo tôi giới thiệu các bạn 1 extension trên chrome hỗ trợ việc kiểm tra data trên elasticsearch gọi là "elasticsearch head":
Link: https://chrome.google.com/webstore/detail/multi-elasticsearch-head/cpmmilfkofbeimbmgiclohpodggeheim
Sau khi cài đặt extension ở trên thành công, click icon extension:
Chọn "Multi Elasticsearch Head" và đây là giao diện:
Các bạn click chọn tab "Structured Query" sẽ thấy hiện chưa có bất kỳ document nào:
Vậy là cơ bản đã xong phần cài đặt và cấu hình Elasticsearch. Tiếp theo tôi sẽ tạo một project với Spring boot và Spring data elasticsearch.
2. Cấu trúc thư mục:
3. Nội dung file pom:
4. Tạo class "Employee" trong package "com.example.elasticsearch.model":
Trong class "Employee" có 2 annotation, tôi sẽ phân tích từng cái:
-
@Document: Nếu các bạn đã từng làm việc với Hibernate thì sẽ biết "@Table" -> "@Document" cũng tương tự như "@Table", nó sẽ thực hiện ánh xạ class "Employee" này với index name là "employee"
-
@Id: Annotation dùng để đánh dấu cho biết giá trị biến "id" này là khoá chính
Và có 1 lưu ý, với phiên bản Elasticsearch 8.x.x thì đã bỏ thuộc tính "type". Các bạn có thể tham khảo thông tin này trang chủ elastic:
Link: https://www.elastic.co/guide/en/elasticsearch/reference/current/removal-of-types.html
Tiếp tục, khi tạo xong class "Employee", tôi tiến hành start project và lên giao diện "Elasticsearch head" để kiểm tra xem "document" đã được tạo chưa:
Click vào icon được khoanh đỏ để reset lại trạng thái:
Sau khi reset thành công sẽ thấy từ "Green" chuyển thành "Yellow" và đã có "document" với index name là "employee"
Tôi click chọn tab "Structured Query" thấy "document" với index name là "employee" được tạo nhưng hiện tại chưa có data nào:
5. Tạo 1 interface "EmployeeRepository" trong package "com.example.elasticsearch.repository":
Trong interface "EmployeeRepository" tôi cho kế thừa "ElasticsearchRepository" và khai báo 1 method "findByName", thực sự mặc định "ElasticsearchRepository" đã hỗ trợ 1 số method như "findAll()"; "findById()";"findByName()";...
Cần khai báo package chứa những repository trong class khởi động "ElasticSearchApplication", dùng annotation "@EnableElasticsearchRepositories":
6. Tạo 1 class "EmployeeController" trong package "com.example.elasticsearch.controller":
Trong class controller tôi cần sử dụng những method "findAll()"; "findById()";"findByName()" được hỗ trợ bởi "ElasticsearchRepository", vì vậy tôi sẽ dùng annotation "@AutoWired" để khai báo "EmployeeRepository"
Tôi tiến hành test với Postman:
-
Call api tạo mới employee với data body là 1 list:
[ { "id":"11", "name":"A", "title":"SE", "age": 31 }, { "id":"12", "name":"C", "title":"BA", "age": 22 }]
Kết quả test:
Kiểm tra lỗi:
Đầu tiên, tôi sẽ lên Elasticsearch head và kiểm tra xem dữ liệu đã được thêm mới thành công hay chưa:
Các bạn có thể thấy index name "employee" hiện đang có 2 docs -> dữ liệu đã được thêm thành công và tại mục "Results:" đang để mặc định là "Table" tôi sẽ chọn lại thành "JSON" và click "Search" để thấy tất cả dữ liệu đang có:
Kết quả cho thấy dữ liệu được tạo thành công, vậy tại sao lại báo lỗi? thực sự lỗi này gặp ở phiên bản Elasticsearch 8.x.x bởi vì tôi có nói ở đầu bài viết là với phiên bản Elasticsearch 8.x.x thì thuộc tính "type" đã bị xoá và chỉ có những phiên bản cũ hơn mới có thuộc tính "type"
Đây là nguyên nhân văng ra lỗi, các bạn thấy lỗi tôi khoanh đỏ ở trên tại class "DocWriteResponse", trong class này tại constructor khi gán giá trị cho thuộc tính "type" nó yêu cầu thuộc tính "type" không được null:
Và vì thế khi thấy "type" null -> văng lỗi
Thực sự dữ liệu đã được thêm thành công nhưng làm thế nào để không văng lỗi, tôi có 2 giải pháp:
-
Giải pháp thứ 1(khuyên dùng): Tại về phiên bản elasticsearch 7.x.x trở về trước -> sẽ không có lỗi xảy ra
-
Giải pháp thứ 2: Bọc "try{}catch()".
Tôi sẽ thử cả 2 giải pháp ở trên:
- Giải pháp thứ 2:
Kết quả khi call api tạo mới employee:
Kết quả khi call api delete employee by id:
Kết quả khi call api cập nhật thông tin employee by id:
Kết quả khi trích xuất thông tin employee by id:
=> Dữ liệu được xử lý thành công nhưng giải pháp này không hiệu quả bởi vì có thể sẽ bị bỏ qua những lỗi khác và nếu bạn muốn khoanh vùng những lỗi nào cho qua hoặc không thì cần phải lấy ra tên lỗi và loại trừ ra. Có thể dùng "{exeption}.getClass().getSimpleName()" để lấy ra tên lỗi
Tôi sẽ dùng giải pháp thứ 1, dùng phiên bản Elasticsearch cũ hơn, ở đây tôi dùng phiên bản 7.17.6(phiên bản cuối cùng của 7.x.x). Cấu hình cũng tương tự như tôi đã giải thích ở đầu bài viết
Kiểm tra thông tin phiên bản:
Kiểm tra Elasticsearch head:
Chưa có document nào
Start project:
Kiểm tra lại Elasticsearch head:
Chưa có bất kỳ data nào
Cập nhật lại "EmployeeControler", bỏ "try{}catch()":
Tiến hành test:
Kết quả khi call api tạo mới employee:
Kết quả khi call api delete employee by id:
Kết quả khi call api cập nhật thông tin employee by id:
Kết quả khi trích xuất thông tin employee by id:
=> Các bạn thấy với phiên bản Elasticsearch 7.x.x vẫn có thuộc tính "type" và quá trình call api không có bất kỳ lỗi nào xảy ra
Bài viết khá dài nên tôi sẽ dừng tại đây và trong bài viết sau tôi sẽ tạo 1 project Spring boot với thymeleaf và spring data elasticsearch.