0

I want to make a correct query using Hibernate Search, which contains the following parameters:

1) breaking the phrase into words and searching every word in several fields;

2) ability to search part of the word;

3) ignoring uppercase and lowercase

In my code I've implemented it using terms iteration. But I want to make the most of the Hibernate Search.

@Repository
public class ProductSearch {
    @PersistenceContext
    EntityManager em;

    public List<Product> searchProducts(String text) throws InterruptedException, ParseException {


        List<Product> allResults = new ArrayList<>();
        for (String word : text.toLowerCase().split(" ")) {
            Query wildcardQuery = getQueryBuilder()
                    .keyword()
                    .wildcard()
                    .onFields("productNumber", "category.uaName")
                    .matching("*" + word + "**")
                    .createQuery();

            List<Product> results = getJpaQuery(wildcardQuery).getResultList();
            for (Product result : results) {
                if(!allResults.contains(result)) {
                    allResults.add(result);
                }
            }
        }

        return allResults;
    }

    private FullTextQuery getJpaQuery(org.apache.lucene.search.Query luceneQuery) {

        FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(em);

        return fullTextEntityManager.createFullTextQuery(luceneQuery, Product.class);
    }

    private QueryBuilder getQueryBuilder() throws InterruptedException {

        FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(em);
        fullTextEntityManager.createIndexer().startAndWait();

        return fullTextEntityManager.getSearchFactory()
                .buildQueryBuilder()
                .forEntity(Product.class)
                .get();
    }
}

Can anyone help me, because I am new to Hibernate Search?

Maybe someone can share their own code? I will be very grateful

I've solved my problem but have two versions of code:

Version 1:


    public List<Product> searchProducts(String text) throws InterruptedException, ParseException {
String[] fields = {"productNumber", "category.uaName"};
        FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(em);
        fullTextEntityManager.createIndexer().startAndWait();
        org.apache.lucene.queryparser.classic.MultiFieldQueryParser parser = new MultiFieldQueryParser(
                fields,

                fullTextEntityManager.getSearchFactory().getAnalyzer("customanalyzer_query")
        );
        org.apache.lucene.search.Query luceneQuery =
                parser.parse( text);
        org.hibernate.search.jpa.FullTextQuery fullTextQuery =
                fullTextEntityManager.createFullTextQuery( luceneQuery, Product.class );
        List result = fullTextQuery.getResultList();
return result;
    }

Version 2:

    public List<Product> searchProducts(String text) throws InterruptedException, ParseException {

        Query query = getQueryBuilder()
                .keyword()
                .onFields("productNumber", "category.uaName")
                .matching(text)
                .createQuery();

        List<Product> results = getJpaQuery(query).getResultList();

        return results;
    }

    private FullTextQuery getJpaQuery(org.apache.lucene.search.Query luceneQuery) {

        FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(em);

        return fullTextEntityManager.createFullTextQuery(luceneQuery, Product.class);
    }

    private QueryBuilder getQueryBuilder() throws InterruptedException {

        FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(em);
        fullTextEntityManager.createIndexer().startAndWait();

        return fullTextEntityManager.getSearchFactory()
                .buildQueryBuilder()
                .forEntity(Product.class)
                .overridesForField("productNumber", "customanalyzer_query")
                .overridesForField("category.uaName", "customanalyzer_query")
                .get();

    }

1 Answers1

0

As was already answered here, the easiest solution is simply not to use wildcard queries.

Just use an appropriate analyzer with an edge-ngram filter, remove the wildcards from your query string, and remove the .wildcard() in your code. See this answer for more information about the analysis.

yrodiere
  • 9,280
  • 1
  • 13
  • 35
  • Thank you very much for answering and for many helpful articles on this topic. I have two versions of the code that solve my problem. Which version is more rational and practical, in your opinion? Please, see above. I've edited my ask – Taras Svidnytskyy Sep 06 '19 at 13:30
  • Personally I would with #2, since the first solution will parse the query, i.e. it will allow users to control things such as fuzziness, wildcards, perform phrase queries, etc., which requires a special syntax that may be used by mistake and will confuse your users. – yrodiere Sep 09 '19 at 06:13