Hibernate-search 6 MultiFieldQueryParser equivalent

Hello,

i can’t find a way to parse a QueryString with the new predicate API in alpha7

Before i was able to do something like that

String terms = "field1:'test*' AND number1:[X TO *]";
QueryParser parser = new MultiFieldQueryParser(fields, new StandardAnalyzer());
org.apache.lucene.search.Query query= parser.parse(terms);
FullTextQuery fullTextQuery = fullTextSession.createFullTextQuery(query, MyClass.class);
SearchSession s = Search.session(sessionFactory.createEntityManager());
s.search(MyClass.class).predicate(... ? ... )

The predicate need a SearchPredicateTerminalContext so i can’t simply pass my parsed query

Do you have any ideas?

If all you need is a simple syntax so that your users can write simple queries, I would recommend the “simple query string” predicate. It does not support numeric ranges, however.

If you’re using the Lucene backend (not the Elasticsearch backend), you can take advantage of the native API to still use the same parser:

String terms = "field1:'test*' AND number1:[X TO *]";
QueryParser parser = new MultiFieldQueryParser(fields, new StandardAnalyzer());
List<MyClass> hits = searchSession.search( MyClass.class )
        .extension( LuceneExtension.get() )
        .predicate( f -> f.fromLuceneQuery( parser.parse(terms) ) )
        .fetchHits();

The Elasticsearch backend has a similar feature, but expects JSON instead of a Lucene Query.

See https://docs.jboss.org/hibernate/search/6.0/reference/en-US/html_single/#search-dsl-predicate-extensions-lucene-from-lucene-query

SearchSession s = Search.session(sessionFactory.createEntityManager());
List<MyClass> hits = s.search(clazz)
		.extension(ElasticsearchExtension.get())
		.predicate(f -> f.fromJson(
				String.format("{\"bool\":{\"must\":[{\"query_string\":{\"query\":\"%s\"}}]}}", term)
			)
		)
		.fetchHits();

Thanks ! This syntax did it for me :wink:

Nice.

I must warn you that by using String.format, you’re potentially exposing yourself to JSON injection by malicious users. I’d recommend using a JSON library such as GSON instead, building JSONObject instances then converting them to a String.

Yes ofc, it was just for the POC