Reputation: 1194
My application, that uses Hibernate Search 4.5.0.Final, is working fine when I try to search with just one keyword. But if I try to use two keywords, the second keyword is not used by Hibernate Search, just the first one is considered by HS.
For example, if I try to search "James", the search works fine and the application returns all "James" that I have in the index. But if I try to search "James Hetfield", the results are, again, all "James" and not the unique result with name "James Hetfield". I need to treat "James Hetfield" as "James AND Hetfield".
EDIT: I've made a mistake. The search works with two keywords, but with "OR" and not "AND".
My code:
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: " + keywords, e);
throw new DAOException(e);
}
}
Upvotes: 1
Views: 2256
Reputation: 566
Use the key word MUST during query building. 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();
This reference is obtained from the link http://www.baeldung.com/hibernate-search
Upvotes: 0
Reputation: 1194
Found a solution. I've split the String and used BooleanQuery. Thanks to @thomas. Here is my code:
Splitting:
String[] arrKeywords = keywords.split(" ");
this.search(Arrays.asList(arrKeywords));
And then, searching:
public List<Person> search(String keywordsList) throws DAOException {
try {
FullTextEntityManager fullTextEm = Search.getFullTextEntityManager(this.entityManager);
QueryBuilder qb = fullTextEm.getSearchFactory().buildQueryBuilder().forEntity(Person.class).get();
List<Query> queryList = new LinkedList<Query>();
Query query = null;
for (String keyword : keywordsList) {
query = qb.keyword().onFields("name", "email", "username", "phone").matching(keyword).createQuery();
queryList.add(query);
}
BooleanQuery finalQuery = new BooleanQuery();
for (Query q : queryList) {
finalQuery.add(q, Occur.MUST);
}
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: " + keywords, e);
throw new DAOException(e);
}
}
Upvotes: 5