23 Eylül 2021 Perşembe

HibernateSearch Kullanımı

Maven
Açıklaması şöyle
Hibernate Search provides you with both Lucene and ElasticSearch implementations that are highly optimized for full-text search.
Örnek - Lucene
Şöyle yaparız
<dependency>
<groupId>org.Hibernate.search</groupId> <artifactId>Hibernate-search-mapper-orm</artifactId> <version>6.0.2.Final</version> </dependency> <dependency> <groupId>org.Hibernate.search</groupId> <artifactId>Hibernate-search-backend-lucene</artifactId> <version>6.0.2.Final</version> </dependency>
SpringBoot İle Kullanım
Spring için şu kütüphaneyi dahil ederiz
spring-boot-hibernate-search
Index dizinini belirtmek için şöyle yaparız
# HIBERNATE SEARCH
spring.jpa.properties.hibernate.search.backend.directory.root=/home/indexes/
yaml ile şöyle yaparız
server:
    port: 9000

spring:
    datasource:
        url: jdbc:h2:mem:mydb
        username: mozen
        password: password
    jpa:
        open-in-view: false
        properties:
            hibernate:
                search:
                    backend:
                        type: lucene
                        directory.root: ./data/index
Data Model
Entity üzerinde
@Indexed - Sınıfın indeksleneceğini belirtir
@FullTextField - Metin alanlarda arama içindir. Diğer tipte alanlar için başka anotasyonlar var
anotasyonları kullanılır

MassIndexer ile indeksleme başlatılır
SearchSession ile arama yapılır

Repository
Spring için şöyle bir kod ekleriz. Burada @NoRepositoryBean kullanılıyor, böylece bu sınıf repository olarak algılanmaz.
@NoRepositoryBean
public interface SearchRepository<T, ID extends Serializable> 
  extends JpaRepository<T, ID> {

  List<T> searchBy(String text, int limit, String... fields);
}
searchBy metodunun gerçekleştirimini ekleriz.  Spring kuralları gereği interface ismine Impl son ekini vererek yeni bir sınıf yaratırız. Burada SearchSession hibernate sınıfı. Burada fetch() metoduna limit değeri geçiliyor.  
import org.hibernate.search.mapper.orm.session.SearchSession;

@Transactional
public class SearchRepositoryImpl<T, ID extends Serializable> 
  extends SimpleJpaRepository<T, ID>
        implements SearchRepository<T, ID> {

  private final EntityManager entityManager;

  public SearchRepositoryImpl(Class<T> domainClass, EntityManager entityManager) {
    super(domainClass, entityManager);
    this.entityManager = entityManager;
  }

  public SearchRepositoryImpl(
          JpaEntityInformation<T, ID> entityInformation, EntityManager entityManager) {
    super(entityInformation, entityManager);
    this.entityManager = entityManager;
  }

  @Override
  public List<T> searchBy(String text, int limit, String... fields) {

    SearchResult<T> result = getSearchResult(text, limit, fields);

     return result.hits();
  }

  private SearchResult<T> getSearchResult(String text, int limit, String[] fields) {
    SearchSession searchSession = Search.session(entityManager);

    SearchResult<T> result = searchSession
      .search(getDomainClass())
      .where(f -> f.match().fields(fields).matching(text).fuzzy(2))
      .fetch(limit);
    return result;
  }
}
Artık yeni bir repository şöyledir
@Repository
public interface PlantRepository extends SearchRepository<Plant, Long> {
}
Örnek - Sayfalama
Şöyle yaparız. Burada fetch() metoduna offset + limit değerleri geçiliyor. 
@Data
@AllArgsConstructor
@NoArgsConstructor
public class PageDTO<T> {

    private List<T> content;
    private long total;
}

@Override
public PageDTO<T> searchPageBy(String text, int limit, int offset, String... fields) {
  SearchResult<T> result = getSearchResult(text, limit, offset, fields);

  return new PageDTO<T>(result.hits(), result.total().hitCount());
}

private SearchResult<T> getSearchResult(String text, int limit, int offset, 
  String[] fields) {
  SearchSession searchSession = Search.session(entityManager);

  SearchResult<T> result = searchSession
    .search(getDomainClass())
    .where(f -> f.match().fields(fields).matching(text).fuzzy(2))
    .fetch(offset, limit);
    return result;
}



Hiç yorum yok:

Yorum Gönder