简体   繁体   中英

Hibernate-Search wildcard search not returning expected results

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM