Hibernate Search: how to search a full name over separate columns
I have an entity called 'Patient' with string fields called 'firstName', 'lastName' and 'secondLastName' (in Spanish we use both, father and mother family names)
I have a view with a textbox to search patients by name, in which the user may type anything: firstName, lastName, secondLastName, or a combination of these, in any given order. For example, with my name:
firstName: Mauricio, lastName: Ubilla, secondLastName: Carvajal,
If I search "Mauricio Ubilla Carvajal" or even "Mauricio Ubilla" I expect to appear top in the result list. The questions are:
1- How should I define the index for these 3 fields? I did the following:
@Indexed
class Patient {
...
@Field(index=Index.YES, analyze=Analyze.YES, store=Store.NO)
protected String firstName = new String();
@Field(index=Index.YES, analyze=Analyze.YES, store=Store.NO)
protected String lastName = new String();
@Field(index=Index.YES, analyze=Analyze.YES, store=Store.NO)
protected String secondLastName = new String();
...
}
2- How should I build the query? I did this:
QueryBuilder qb = fullTextSession.getSearchFactory().buildQueryBuilder().forEntity(Patient.class).get();
Query luceneQuery = qb.keyword().onFields("firstName", "lastName", "secondLastName").matching(name).createQuery();
However, this is not working for me. It is not throwing any exception, it is just that it is not returning anything. Even if I just search "Mauricio" it doesn't return anything.
But, if I change the query only to match my firstName:
QueryBuilder qb = fullTextSession.getSearchFactory().buildQueryBuilder().forEntity(Patient.class).get();
Query luceneQuery = qb.keyword().onFields("firstName").matching(name).createQuery();
If I search for "Mauricio" it works.
What am I doing wrong? Is there any way to define a composite index for the 3 columns? Should I build my query in a different way? Help me please :( Btw, I'm using Hibernate Search 4.5.1 Over Hibernate 4.3 and Java 1.7
You are using a very old version of Hibernate Search, so it's very possible that you are running into a bug that has been solved in a more recent version. You should really think about upgrading to at least Hibernate Search 5.6 / Hibernate ORM 5.1, or even better to Search 5.8 / ORM 5.2 (requires Java 8).
If you cannot... Another common solution is to index a transient property whose content is the concatenated names:
@Indexed
class Patient {
...
@Field
protected String firstName = "";
@Field
protected String lastName = "";
@Field
protected String secondLastName = "";
...
@javax.persistence.Transient
@Field
public String getFullName() {
// TODO null safety
return firstName + " " + lastName + " " + secondLastName;
}
...
}
Then query on this fullName
:
QueryBuilder qb = fullTextSession.getSearchFactory().buildQueryBuilder().forEntity(Patient.class).get();
Query luceneQuery = qb.keyword().onFields("fullName").matching(name).createQuery();
Note that, on contrary to your initial solution, this will have a negative impact on performance, since indexing a @Transient
field disables some optimizations. But at least it should work.
To answer your second question. You can search using a phrase as a sentence rather than a keyword.
Hibernate Search also supports combining queries using various strategies:
-SHOULD: the query should contain the matching elements of the subquery
-MUST: the query must contain the matching elements of the subquery
-MUST NOT: the query must not contain the matching elements of the subquery
The aggregations are similar to the boolean ones AND, OR and NOT.
Query combinedQuery = queryBuilder
.bool()
.must(queryBuilder.phrase()
.onField("productName).sentence("samsung galaxy s8")
.createQuery())
.must(queryBuilder.keyword()
.onField("productCategory").matching("smartphone")
.createQuery())
.createQuery();
// wrap Lucene query in an Hibernate Query object
org.hibernate.search.jpa.FullTextQuery jpaQuery =
fullTextEntityManager.createFullTextQuery(combinedQuery, Product.class);
// execute search and return results (sorted by relevance as default)
@SuppressWarnings("unchecked")
List<Product> results = jpaQuery.getResultList();
Reference http://www.baeldung.com/hibernate-search
链接地址: http://www.djcxy.com/p/37102.html上一篇: 添加一个标准:字符串应该在集合中