How to search %like% as sql

Hi everyone.
I have problem implementing hibernate search 5 %like% sql.
I have a “title” field on the “Email” class.
With some case search below I want to return the result as “PI_030120220659025592.xml” but the result returned is not as expected.

Search -> Result
PI_03012022065 -> PI_030120220659025592.xml
PI_030120220650 -> not found
592.xml -> not found
92.xml  -> another result

Code implement:

@Entity
@Table(name = "emails")
@Getter
@Setter
@NoArgsConstructor(force = true)
@AllArgsConstructor
@Builder
@Indexed
public class Email implements Serializable {
    private static final long serialVersionUID = 5522175857108981474L;
    
    @Field(analyzer = @Analyzer(definition = "searchTextAnalyzer"))
    private String title;
}

-------------
FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(entityManager);
QueryBuilder qb = fullTextEntityManager.getSearchFactory().buildQueryBuilder().forEntity(Email.class).get();
BooleanJunction<BooleanJunction> bool = qb.bool();

Map<String, String> map = new HashMap<>();
map.put("minGramSize", "1");
map.put("maxGramSize", "100");
 Analyzer analyzer = CustomAnalyzer.builder()
    .withTokenizer( WhitespaceTokenizerFactory.class )
    .addTokenFilter( LowerCaseFilterFactory.class )
    .addTokenFilter( ASCIIFoldingFilterFactory.class )
     .addTokenFilter(EdgeNGramFilterFactory.class, map)
    .build();
List<String> keywords = this.tokenizeString(analyzer, title);
for (String keyword : keywords) {
     bool.must(qb.keyword().boostedTo(5f).wildcard().onFields("title").matching("" + keyword + "").createQuery());
}

---------------------------
public List<String> tokenizeString(Analyzer analyzer, String string) {
        List<String> result = new ArrayList<>();
        try {
            TokenStream stream = analyzer.tokenStream(null, new StringReader(string));
            stream.reset();
            while (stream.incrementToken()) {
                result.add(stream.getAttribute(CharTermAttribute.class).toString().toLowerCase());
            }
            stream.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return result;
    }

Can someone help me figure out where the problem is?
Thank you.

Hey,

Please include the definition of that analyzer.

If you’re tokenizing strings yourself, there’s a high chance you’re doing something wrong. Tokenizing is Lucene’s job, not yours. Did you copy and adapt code you found somewhere? Can you point me to it? I’d like to understand what you’re trying to achieve (or rather, how you’re trying to achieve it).

If you’re trying to apply a different analyzer during indexing and search, you should know that you can define multiple analyzers, and ask Hibernate Search to use a specific one when searching:

QueryBuilder qb = searchFactory.buildQueryBuilder()
    .forEntity( Email.class )
        .overridesForField("title","my-analyzer-used-for-search")
    .get();

Also, I will only mention it once since you must have your reasons to stay on Hibernate Search 5, but upgrading to Hibernate Search 6 would make your life easier, in particular because it supports search analyzers.

yrodiere thank you very much,

I will update to hibernate search 6 :laughing:

1 Like