Reputation: 321
I am implementing Hibernate Search 6 in my Spring Boot Application. I need the capability to search for partial matches, similar to %like% in SQL. From the documentation and other forums, it seems that Hibernate Search 6 has removed the explicit support of match and replaced it with the wild card queries.
However, I am not able to achieve the desired results i.e. %like%. Here's my relevant test bed code to reproduce the scenario:
Test Data:
phonenumber,area_zone,state
9871234567,DL,Delhi
9871234568,HR,Haryana
9871234569,PB,Punjab
9871234578,UP,Uttar Pradesh
9871234579,TS,Telangana
9871234479,AP,Andhra Pradesh
My DTO:
@Entity
@Table(name="PHONENUMBER", uniqueConstraints = {@UniqueConstraint(columnNames = "phonenumber")})
@Indexed
public class PhoneNumber {
@Id
@GeneratedValue
private int id;
//@FullTextField(searchAnalyzer = "custom_analyzer")
@GenericField(sortable= Sortable.YES)
private String phonenumber;
@GenericField(sortable=Sortable.YES)
private String area_zone;
@GenericField(sortable= Sortable.YES)
private String state;
}
Here's the implementation of my Custome JPA Repo for Hibernate Search:
public class CustomSearchRepositoryImpl implements CustomSearchRepository {
@PersistenceContext
private EntityManager em;
//Hibernate Search 6
@Override
public List<PhoneNumber> search(String terms, int limit, int offset) {
System.out.println(">>>>>searching for " + terms);
return Search.session(em).search(PhoneNumber.class)
.where(f -> f.match()
.fields("phonenumber", "area_zone", "state")
.matching(terms))
.fetchHits(offset, limit);
}
}
The search is triggered by the API: /search. The results are:
The search on 'full match' works fine but not for the partial match. Would need recommendations to make the partial search work.
PS: Spring Version is 2.6.7.
Upvotes: 0
Views: 40
Reputation: 428
As mentioned in the Hibernate documentation (https://docs.jboss.org/hibernate/search/6.2/reference/en-US/html_single/#search-dsl-predicate-wildcard), you can use wildcards for your issue.
List<Book> hits = searchSession.search( Book.class )
.where( f -> f.wildcard().field( "description" )
.matching( "rob*t" ) )
.fetchHits( 20 );
Looking at your implementation, you can edit it as shown below to get the wildcard results.
@Override
public List<PhoneNumber> search(String terms, int limit, int offset) {
System.out.println(">>>>>searching for " + terms);
return Search.session(em).search(PhoneNumber.class)
.where(f -> f.wildcard()
.fields("phonenumber", "area_zone", "state")
.matching("*" + terms + "*")) // Enables %LIKE% behavior
.fetchHits(offset, limit);
}
Also you may want to use @FullTextField
(https://docs.jboss.org/hibernate/search/6.2/reference/en-US/html_single/#mapping-directfieldmapping-annotations-fulltextfield) if you need to find partial matches. Refer to the examples in https://docs.jboss.org/hibernate/search/6.2/reference/en-US/html_single/#search-dsl-predicate-wildcard to get an idea about how to use it properly.
Upvotes: 0
Reputation: 2518
Since you are using generic fields, no analysis is applied to them, and as a result only exact matches work in that case, see the corresponding section of the documentation:
For most field types (number, date, …), the match is exact. However, for full-text fields or normalized keyword fields, the value passed to the matching(…) method is analyzed or normalized before being compared to the values in the index.
For wildcard predicates see this part of the documentation
List<Book> hits = searchSession.search( Book.class )
.where( f -> f.wildcard().field( "description" )
.matching( "rob*t" ) )
.fetchHits( 20 );
if you want to be able to find partial matches with the match predicate the field should be annotated as @FullTextField
and you should consider using ngram filter in your custom analyser applied to such field.
Upvotes: 1