[Elasticsearch - Java] Tích hợp với Hibernate (Hibernate Search)
Hầu hết mọi người đều đã nghe về Hibernate framework, nhưng không phải ai cũng biết rằng dưới hệ sinh thái của Hibernate, có một dự án rất hữu ích gọi là Hibernate Search.
Hibernate Search giúp lập chỉ mục (indexing) các đối tượng một cách tự động và hỗ trợ full-text search cũng như geolocation search với hiệu suất cao. Dự án này ban đầu chỉ là một lớp kết nối giữa Hibernate và Apache Lucene, nhưng từ phiên bản Hibernate Search 5.7.0, nó đã hỗ trợ tích hợp với Elasticsearch.
Điều này có nghĩa là, nếu bạn đang sử dụng Hibernate để quản lý persistence layer, bạn có thể dễ dàng tích hợp Elasticsearch để bổ sung khả năng tìm kiếm mạnh mẽ mà không cần thay đổi quá nhiều trong ứng dụng của mình.
Cách Hibernate Search Hoạt Động Với Elasticsearch
Dưới đây là mô hình dữ liệu catalog của chúng ta, được biểu diễn bằng JPA entities và sử dụng Hibernate Search annotations để tích hợp với Elasticsearch.
Book entity
@Entity
@Table(name = "BOOKS")
@Indexed(index = "catalog")
public class Book {
@Id
@Field(name = "isbn", analyze = Analyze.NO)
private String id;
@Field
@Column(name = "TITLE", nullable = false)
private String title;
@IndexedEmbedded(depth = 1)
@ElementCollection
private Set<Category> categories = new HashSet<>();
@Field(analyze = Analyze.NO)
@Column(name = "PUBLISHER", nullable = false)
private String publisher;
@Field
@Column(name = "DESCRIPTION", nullable = false, length = 4096)
private String description;
@Field(name = "published_date", analyze = Analyze.NO)
@Column(name = "PUBLISHED_DATE", nullable = false)
@DateBridge(resolution = Resolution.DAY)
private LocalDate publishedDate;
@NumericField
@Field(name = "rating")
@Column(name = "RATING", nullable = false)
private int rating;
@IndexedEmbedded
@ManyToMany
private Set<Author> authors = new HashSet<>();
}
Như bạn thấy, đây là một JPA entity quen thuộc với một số Hibernate Search annotations như @Field
, @DateBridge
, @IndexedEmbedded
, giúp tự động lập chỉ mục dữ liệu lên Elasticsearch.
Tích Hợp Hibernate Search Với Spring Boot
Việc cấu hình Hibernate Search để sử dụng Elasticsearch làm backend khá đơn giản trong Spring Boot. Chỉ cần thêm một vài dòng vào application.yml
:
spring:
jpa:
properties:
hibernate.search.default.indexmanager: elasticsearch
hibernate.search.default.elasticsearch.host: https://localhost:9200
Mỗi khi một thực thể Book hoặc Author được tạo, cập nhật hoặc xóa, Hibernate Search sẽ tự động đồng bộ với Elasticsearch, hoàn toàn trong suốt với ứng dụng của bạn.
Tìm Kiếm Với Hibernate Search
Hibernate Search cung cấp một lớp Query DSL dựa trên Apache Lucene queries, đồng thời cũng cho phép sử dụng một số tính năng gốc của Elasticsearch.
Ví dụ, tìm kiếm tất cả các books thuộc danh mục "analytics"
và có tác giả "Tong"
:
@Autowired private EntityManager entityManager;
final FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(entityManager);
final QueryBuilder qb = fullTextEntityManager.getSearchFactory()
.buildQueryBuilder()
.forEntity(Book.class)
.get();
final FullTextQuery query = fullTextEntityManager.createFullTextQuery(
qb.bool()
.must(qb.keyword().onField("categories.name").matching("analytics").createQuery())
.must(qb.keyword().onField("authors.last_name").matching("Tong").createQuery())
.createQuery(),
Book.class
);
final List<Book> books = query.getResultList();
Cú pháp này rất giống với Query DSL của Elasticsearch, nên nếu bạn đã quen thuộc với Elasticsearch, việc sử dụng Hibernate Search sẽ trở nên dễ dàng.
Một Số Hạn Chế Cần Lưu Ý
Mặc dù Hibernate Search cung cấp một cách tích hợp nhanh chóng giữa Hibernate và Elasticsearch, nhưng nó cũng có một số hạn chế:
- Chỉ hỗ trợ Elasticsearch 2.4.4 tại thời điểm tài liệu này được viết, tức là chưa tương thích với các phiên bản 5.x hoặc cao hơn.
- Bộ API hạn chế, đặc biệt là Query DSL, chưa hỗ trợ đầy đủ tất cả các tính năng của Elasticsearch.
Tuy nhiên, nếu bạn đang sử dụng Hibernate và muốn thêm full-text search vào ứng dụng của mình một cách nhanh chóng, Hibernate Search vẫn là một lựa chọn rất đáng cân nhắc. 🚀
All rights reserved