我们正在使用Spring MVC,Spring和Hibernate开发Web应用程序.
我们需要为我们的应用程序添加有效的自由文本搜索功能.为此,我们考虑使用Hibernate Search(它使用Lucene)或直接使用lucene.
对于我们来说最好的选择是什么,因为我们已经在我们的应用程序中使用了hibernate?一个人的优点和缺点是什么?
谢谢.
我的索引中有非常多的文档,我需要编写一个返回lucence索引中文档总数的方法.目前我使用*通配符来获取所有记录并返回totalHits的值.
问题是,当查询加载所有对象时,它需要花费很多时间,虽然我不需要加载对象,但我的要求是在不加载文档的情况下获取记录总数.
当我尝试仅使用一个关键字进行搜索时,使用Hibernate Search 4.5.0.Final的应用程序运行正常。但是,如果我尝试使用两个关键字,那么Hibernate Search不会使用第二个关键字,HS只会考虑第一个。
例如,如果我尝试搜索“ James”,则搜索工作正常,并且应用程序返回索引中包含的所有“ James”。但是,如果我尝试搜索“ James Hetfield”,结果还是所有“ James”,而不是名称为“ James Hetfield”的唯一结果。我需要将“ James Hetfield”视为“ James AND Hetfield”。
编辑:我犯了一个错误。搜索使用两个关键字,但是使用“ OR”而不是“ AND”。
我的代码:
public List<Person> search(String keywords) throws DAOException {
try {
FullTextEntityManager fullTextEm = Search.getFullTextEntityManager(this.entityManager);
QueryBuilder qb = fullTextEm.getSearchFactory().buildQueryBuilder().forEntity(Person.class).get();
Query query = qb.keyword().onFields("name", "email", "username", "phone").matching(keywords).createQuery();
FullTextQuery fullTextQuery = fullTextEm.createFullTextQuery(query);
fullTextQuery.setProjection("name", "email", "username", "phone");
Sort sortField = new Sort(new SortField("name_order", SortField.STRING));
fullTextQuery.setSort(sortField);
return fullTextQuery.getResultList();
}
catch (Exception e) {
logger.error("Error searching index: " + …Run Code Online (Sandbox Code Playgroud) 我有一个使用Hibernate Search(由Lucene索引支持)和Infinispan的应用程序.我没有 使用Hibernate Core来加载我的数据(我认为这应该没问题).
在启动时,应用程序会从各种来源将大量数据加载到Infinispan缓存中.我发现如果我们离开自动索引(即没有指定hibernate.search.indexing_strategy = manual),缓存插入(和相关的索引)会占用大量内存并且通常根本不会完成.为了解决这个问题,我禁用了自动索引,并在插入所有初始数据后在缓存上运行批量/质量索引器 - 这只需几秒钟就可以正常工作.
我的问题是我定期插入/更新/删除缓存中的项目,我找不到告诉Infinispan或Hibernate Search [重新]索引这些项目的方法.我可以从Hibernate Search Docs中找到最接近的Hibernate会话,并且只能在托管对象上运行.我不通过Hibernate加载数据,所以这是不可能的.
如何通过API调用Infinispan或Hibernate Search来索引单个项目?
我期待您提供任何帮助,如果您需要任何其他信息,请告诉我们.
谢谢,詹姆斯
我有一个使用Hibernate Search的相当简单的Spring Boot 1.5.2应用程序。JPA的东西很好用。
运行以下搜索时,我得到原因:java.lang.ClassNotFoundException:org.hibernate.query.ParameterMetadata。
该代码看起来像这样。曾经在Wildfly中运行,但是我正在迁移到Spring Boot。
FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(em);
QueryBuilder qb = fullTextEntityManager.getSearchFactory()
.buildQueryBuilder()
.forEntity(Customer.class)
.get();
org.apache.lucene.search.Query
luceneQuery = qb.keyword()
.wildcard()
.onField("primaryParty.firstName")
.andField("primaryParty.sureName")
.andField("customerNumber")
.matching(query.trim() + "*")
.createQuery();
javax.persistence.Query jpaQuery =
fullTextEntityManager.createFullTextQuery(luceneQuery, Customer.class);
List<Customer> result = jpaQuery.getResultList();
Run Code Online (Sandbox Code Playgroud)
Hibernate Core 5.0.12是通过Spring Boot引入的,但是该类不存在。
据此:https : //cia.sourceforge.io/tattleTaleReport/jar/hibernate-search-orm-5.7.0.Final.jar.html
我应该期望在hibernate-search-orm 5.7.0.Final中找到它。但是从我可以看到的结果来看,这个jar只包含org.hibernate.search包,没有org.hibernate.query包。也无法在该jar的任何其他包中找到该类,但是它存在于类路径上的许多其他包中。
是问题
javax.persistence.Query
Run Code Online (Sandbox Code Playgroud)
如果是这样,该怎么用呢?还是其他地方的问题?
我的Hibernate Search分析器配置存在一些问题.我的一个索引实体("Hospital")有一个String字段("name"),它可以包含长度为1-40的值.我希望能够通过搜索一个字符找到一个实体(因为有可能,医院有单个字符名称).
@Indexed(index = "HospitalIndex")
@AnalyzerDef(name = "ngram",
tokenizer = @TokenizerDef(factory = StandardTokenizerFactory.class),
filters = {
@TokenFilterDef(factory = StandardFilterFactory.class),
@TokenFilterDef(factory = LowerCaseFilterFactory.class),
@TokenFilterDef(factory = NGramFilterFactory.class,
params = {
@Parameter(name = "minGramSize", value = "1"),
@Parameter(name = "maxGramSize", value = "40")})
})
public class Hospital {
@Field(index = Index.YES, analyze = Analyze.YES, store = Store.NO, analyzer = @Analyzer(definition = "ngram"))
private String name = "";
}
Run Code Online (Sandbox Code Playgroud)
如果我添加名为"My Test Hospital"的医院,Lucene索引如下所示:
1 name al
1 name e
1 name es
1 name est …Run Code Online (Sandbox Code Playgroud) 在我的项目中,我们使用带有 lucene 分析器和太阳能的休眠搜索 4.5。我为我的客户提供了一个文本字段。当他们输入一个短语时,我想找到User名称中包含给定短语的所有实体。
例如,考虑在数据库中有以下标题的条目列表:
[ Alan Smith, John Cane, Juno Taylor, Tom Caner Junior ]
Run Code Online (Sandbox Code Playgroud)
jun应该返回Juno Taylor和Tom Caner Junior
an应该返回Alan Smith,John Cane并且Tom Caner Junior
@AnalyzerDef(name = "customanalyzer", tokenizer = @TokenizerDef(factory = WhitespaceTokenizerFactory.class), filters = {
@TokenFilterDef(factory = LowerCaseFilterFactory.class),
@TokenFilterDef(factory = SnowballPorterFilterFactory.class, params = { @Parameter(name = "language", value = "English") })
})
@Analyzer(definition = "customanalyzer")
public class Student implements Serializable {
@Column(name = "Fname")
@Field(index = Index.YES, …Run Code Online (Sandbox Code Playgroud) 对于特定的医疗中心,我有以下查询以全名搜索患者:
MustJunction mj = qb.bool().must(qb.keyword()
.onField("medicalCenter.id")
.matching(medicalCenter.getId())
.createQuery());
for(String term: terms)
if(!term.equals(""))
mj.must(qb.keyword()
.onField("fullName")
.matching(term+"*")
.createQuery());
Run Code Online (Sandbox Code Playgroud)
并且它工作得很好,但前提是用户键入患者的完整名字和/或姓氏.
但是,即使用户键入firstname或lastname 的一部分,我也希望能够工作.
例如,如果有一个名为"Bilbo Baggins"的病人,我希望搜索找到他,当用户输入"Bilbo Baggins",Bilbo,"Baggins"时,或者即使他只输入"Bil"或"Bag"
为此,我修改了上面的查询,如下所示:
MustJunction mj = qb.bool().must(qb.keyword()
.onField("medicalCenter.id")
.matching(medicalCenter.getId())
.createQuery());
for(String term: terms)
if(!term.equals(""))
mj.must(qb.keyword()
.wildcard()
.onField("fullName")
.matching(term+"*")
.createQuery());
Run Code Online (Sandbox Code Playgroud)
注意我在调用onField()之前如何添加wildcard()函数
但是,这会中断搜索并返回无结果.我究竟做错了什么?
我正在尝试将我的应用程序迁移到使用Hibernate Search的Spring Boot 2.我在启动应用时遇到错误:
java.lang.NoSuchFieldError: sessionjava.lang.ClassNotFoundException: org.hibernate.search.jpa.SearchAn SPI class of type org.apache.lucene.codecs.Codec with name 'Lucene53' does not existNoClassDefFoundError: org/hibernate/resource/beans/spi/ManagedBeanRegistry有关信息,目前Spring Boot 2.0.3.RELEASE版本使用Hibernate核心依赖5.2.4.Final
任何想法,使用哪个版本?
Guillaume回答并彻底清理工作区和索引后更新
使用5.9版本,异常已演变为 No transactional EntityManager available
最后一句话
最后一个错误是通过添加@Transactional方法来修复的,但它在没有的情况下在Spring Boot 1中工作.奇怪的...
当我运行代码中显示的 searchByKeywords 方法时,我收到一条关于缺少 org.hibernate.query.internal.ParameterMetadataImpl 构造函数的错误消息:
java.lang.NoSuchMethodError: org.hibernate.query.internal.ParameterMetadataImpl.<init>([Lorg/hibernate/engine/query/spi/OrdinalParameterDescriptor;Ljava/util/Map;)V
at org.hibernate.search.impl.FullTextSessionImpl.createFullTextQuery(FullTextSessionImpl.java:88) ~[hibernate-search-orm-5.9.2.Final.jar:5.9.2.Final]
at org.hibernate.search.impl.FullTextSessionImpl.createFullTextQuery(FullTextSessionImpl.java:78) ~[hibernate-search-orm-5.9.2.Final.jar:5.9.2.Final]
at org.hibernate.search.impl.FullTextSessionImpl.createFullTextQuery(FullTextSessionImpl.java:52) ~[hibernate-search-orm-5.9.2.Final.jar:5.9.2.Final]
at de.estructor.portal.data.jpa.repo.training.TrainingRepoSearchImpl.searchByKeywords(TrainingRepoSearchImpl.java:50) ~[classes/:na]
Run Code Online (Sandbox Code Playgroud)
当我要求我的 IDE 打开文件时,我可以看到构造函数存在为
public ParameterMetadataImpl(
Map<Integer,OrdinalParameterDescriptor> ordinalDescriptorMap,
Map<String, NamedParameterDescriptor> namedDescriptorMap) {
Run Code Online (Sandbox Code Playgroud)
这是我的 pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>de.estructor</groupId>
<artifactId>data</artifactId>
<version>0.0.1</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.1.RELEASE</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-data</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency> …Run Code Online (Sandbox Code Playgroud) hibernate-search ×10
lucene ×8
hibernate ×4
java ×4
spring-boot ×3
spring ×2
analyzer ×1
infinispan ×1
n-gram ×1
solar ×1
wildcard ×1