如何在 Spring Boot with JPA + MySQL 中实现全文搜索
How to implement full text search in Spring Boot with JPA + MySQL
public class Product {
private Long id;
private String name;
private String description;
}
有什么方法可以使用 JpaRepository 实现对 class 产品描述的全文搜索?
您可以使用 Hibernate Search, a library that plugs into Hibernate ORM to index your entities into a Lucene index on the filesystem, on the fly, when you send them to your database. See the Getting started guide.
(编辑: 如今 Hibernate Search 还支持使用 Elasticsearch 作为后端;它会自动在 Elasticsearch 或本地 Lucene 索引中复制部分数据库,无论您选择哪个。 )
查询 Lucene/Elasticsearch 索引与查询数据库有点不同,因此您不能像平常那样使用 HQL 或 Criteria。 Hibernate Search 提供了自己的查询 DSL。
如果你想在你的存储库中使用自动神奇生成的方法实现,你可以依赖 Snowdrop,这是一个 Hibernate Search / Spring 数据集成,但还没有一会儿更新。
最好的办法可能是在存储库接口中定义查询方法,然后使用 Hibernate Search API 自行实现它们。它真的没有那么复杂,除了最明显的查询外,通常推荐使用它。参见 the Spring Data JPA documentation。
基本上您会得到类似于下面代码段的内容。请记住,在此工作之前,您需要重新索引数据库!有关详细信息,请参阅 getting started guide。
使用 Hibernate Search 6+:
@Indexed // Add this
public class Product {
private Long id;
@FullTextField // And this
private String name;
@FullTextField // And this
private String description;
}
public interface ProductRepository extends CrudRepository<Product, Long>, CustomizedProductRepository {
// Declare automatically generated methods here
}
public interface CustomizedProductRepository {
List<Product> search(String terms, int limit, int offset);
}
public class CustomizedProductRepositoryImpl implements CustomizedProductRepository {
@PersistenceContext
private EntityManager em;
@Override
public List<Product> search(String terms, int limit, int offset) {
return Search.session(em).search(Product.class)
.where(f -> f.match()
.fields("name", "description")
.matching(terms))
.fetchHits(offset, limit);
}
}
或使用 Hibernate Search 5:
@Indexed // Add this
public class Product {
private Long id;
@Field // And this
private String name;
@Field // And this
private String description;
}
public interface ProductRepository extends CrudRepository<Product, Long>, CustomizedProductRepository {
// Declare automatically generated methods here
}
public interface CustomizedProductRepository {
List<Product> search(String terms, int limit, int offset);
}
public class CustomizedProductRepositoryImpl implements CustomizedProductRepository {
@PersistenceContext
private EntityManager em;
@Override
public List<Product> search(String terms, int limit, int offset) {
FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(em);
QueryBuilder queryBuilder = fullTextEntityManager.getSearchFactory()
.buildQueryBuilder().forEntity(Product.class).get();
org.apache.lucene.search.Query luceneQuery = queryBuilder
.keyword()
.onFields("name", "description")
.matching(terms)
.createQuery();
// wrap Lucene query in a javax.persistence.Query
javax.persistence.Query jpaQuery =
fullTextEntityManager.createFullTextQuery(luceneQuery, Product.class);
jpaQuery.setMaxResults(limit);
jpaQuery.setFirstResult(offset);
// execute search
return jpaQuery.getResultList();
}
}
public class Product {
private Long id;
private String name;
private String description;
}
有什么方法可以使用 JpaRepository 实现对 class 产品描述的全文搜索?
您可以使用 Hibernate Search, a library that plugs into Hibernate ORM to index your entities into a Lucene index on the filesystem, on the fly, when you send them to your database. See the Getting started guide.
(编辑: 如今 Hibernate Search 还支持使用 Elasticsearch 作为后端;它会自动在 Elasticsearch 或本地 Lucene 索引中复制部分数据库,无论您选择哪个。 )
查询 Lucene/Elasticsearch 索引与查询数据库有点不同,因此您不能像平常那样使用 HQL 或 Criteria。 Hibernate Search 提供了自己的查询 DSL。
如果你想在你的存储库中使用自动神奇生成的方法实现,你可以依赖 Snowdrop,这是一个 Hibernate Search / Spring 数据集成,但还没有一会儿更新。
最好的办法可能是在存储库接口中定义查询方法,然后使用 Hibernate Search API 自行实现它们。它真的没有那么复杂,除了最明显的查询外,通常推荐使用它。参见 the Spring Data JPA documentation。
基本上您会得到类似于下面代码段的内容。请记住,在此工作之前,您需要重新索引数据库!有关详细信息,请参阅 getting started guide。
使用 Hibernate Search 6+:
@Indexed // Add this
public class Product {
private Long id;
@FullTextField // And this
private String name;
@FullTextField // And this
private String description;
}
public interface ProductRepository extends CrudRepository<Product, Long>, CustomizedProductRepository {
// Declare automatically generated methods here
}
public interface CustomizedProductRepository {
List<Product> search(String terms, int limit, int offset);
}
public class CustomizedProductRepositoryImpl implements CustomizedProductRepository {
@PersistenceContext
private EntityManager em;
@Override
public List<Product> search(String terms, int limit, int offset) {
return Search.session(em).search(Product.class)
.where(f -> f.match()
.fields("name", "description")
.matching(terms))
.fetchHits(offset, limit);
}
}
或使用 Hibernate Search 5:
@Indexed // Add this
public class Product {
private Long id;
@Field // And this
private String name;
@Field // And this
private String description;
}
public interface ProductRepository extends CrudRepository<Product, Long>, CustomizedProductRepository {
// Declare automatically generated methods here
}
public interface CustomizedProductRepository {
List<Product> search(String terms, int limit, int offset);
}
public class CustomizedProductRepositoryImpl implements CustomizedProductRepository {
@PersistenceContext
private EntityManager em;
@Override
public List<Product> search(String terms, int limit, int offset) {
FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(em);
QueryBuilder queryBuilder = fullTextEntityManager.getSearchFactory()
.buildQueryBuilder().forEntity(Product.class).get();
org.apache.lucene.search.Query luceneQuery = queryBuilder
.keyword()
.onFields("name", "description")
.matching(terms)
.createQuery();
// wrap Lucene query in a javax.persistence.Query
javax.persistence.Query jpaQuery =
fullTextEntityManager.createFullTextQuery(luceneQuery, Product.class);
jpaQuery.setMaxResults(limit);
jpaQuery.setFirstResult(offset);
// execute search
return jpaQuery.getResultList();
}
}