I have the following indexed POJO that I am trying to query on:
@Entity
@Indexed
@AnalyzerDef(name="userAnalyzer",
tokenizer = @TokenizerDef(factory=StandardTokenizerFactory.class),
filters = {
@TokenFilterDef(factory=LowerCaseFilterFactory.class),
@TokenFilterDef(factory=SnowballPorterFilterFactory.class, params = {
@Parameter(name="language", value="English"
})
}
)
public class User {
@Id
private long id;
@IndexEmbedded
private List<Address> addresses; // Address.street is what I am looking for
@Field
private String firstName;
@Field
private String lastName;
private List<AKA> akas;
private List<Wife> wives;
...
}
Essentially I am trying to do the following SQL in Hibernate-search (Lucene):
select u.*
from User
where u.firstName like ':fname%'
and u.lastName like ':lname%'
The following is what I have that doesn't work consistently:
...
if(Objects.nonNull(u.getFirstName()){
luceneBoolQuery.must(queryBuilder.keyword().wildcard().onField("firstName").matching(u.getFirstName().toLowerCase()).createQuery());
}
if(Objects.nonNull(u.getLastName()){
luceneBoolQuery.must(queryBuilder.keyword().wildcard().onField("lastName").matching(u.getLastName().toLowerCase()).createQuery());
}
Query luceneQuery = luceneBoolQuery.createQuery();
Query jpaQuery = fullTextEntityManager.createFullTextQuery(luceneQuery, User.class);
...
...
Can someone help me craft this query to pull back what the SQL above would return?
Your queries don't include the string wildcard character ('*'). Maybe this will work as you want?
...
if(Objects.nonNull(u.getFirstName()){
luceneBoolQuery.must(queryBuilder.keyword().wildcard().onField("firstName").matching(u.getFirstName().toLowerCase() + "*").createQuery());
}
if(Objects.nonNull(u.getLastName()){
luceneBoolQuery.must(queryBuilder.keyword().wildcard().onField("lastName").matching(u.getLastName().toLowerCase() + "*").createQuery());
}
Query luceneQuery = luceneBoolQuery.createQuery();
Query jpaQuery = fullTextEntityManager.createFullTextQuery(luceneQuery, User.class);
...
...
Also, your analyzer is only defined, not attributed to your fields, so your search will still be case sensitive.
You'll need add @Analyzer
annotations:
@Field
@Analyzer(definition = "userAnalyzer")
private String firstName;
@Field
@Analyzer(definition = "userAnalyzer")
private String lastName;
Alternatively, you may add the annotation on the whole class:
@Entity
@Indexed
@AnalyzerDef(name="userAnalyzer",
tokenizer = @TokenizerDef(factory=StandardTokenizerFactory.class),
filters = {
@TokenFilterDef(factory=LowerCaseFilterFactory.class),
@TokenFilterDef(factory=SnowballPorterFilterFactory.class, params = {
@Parameter(name="language", value="English"
})
}
)
@Analyzer(definition="userAnalyzer") // Difference HERE
public class User {
...
... and of course, you'll have to reindex your data before testing.
Please refer to the reference documentation for further information about using analyzers: https://docs.jboss.org/hibernate/stable/search/reference/en-US/html_single/#_analyzer
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.