I am currently upgrading our server-application from HS-5.9.2-Final to HS-6.1.4-Final and i am stuck.
Constraints are:
- HS-6.1.4-Final with Lucene-backend
- we need to make all fields of our entities available for searches
- mostly for historic reasons searches come as Lucene-query strings (e.g. “firstName:John”)
I made a small POC and was able to search successfully on all entity-fields annotated with KeywordField and FulltextField.
But so far no luck searching fields annotated with GenericField (e.g. int-types). I tested my lucene-queries using luke and had no problem searching over numeric- or text-fields.
My entity looks like:
...
@Entity
@Indexed
@Getter
@Setter
@ToString
@RequiredArgsConstructor
public class Customer extends AbstractEntity {
@GenericField(sortable = Sortable.YES)
int age;
@FullTextField
@Enumerated(EnumType.STRING)
Gender gender;
@FullTextField
@KeywordField(name = "firstName_sort", sortable = Sortable.YES)
private String firstName;
@FullTextField
@KeywordField(name = "lastName_sort", sortable = Sortable.YES)
private String lastName;
@FullTextField
@KeywordField(name = "identification_sort", sortable = Sortable.YES)
@Column(unique = true)
private String identification;
@FullTextField
@KeywordField(name = "email_sort", sortable = Sortable.YES)
private String email;
@OneToMany(mappedBy = "customer", cascade = CascadeType.ALL)
@JsonBackReference
@ToString.Exclude
private List<Book> books;
...
}
Searches i can run successfully are:
@ParameterizedTest
@CsvSource({
"firstName:Johnny,1", // exact field-match
"firstName:Johnny OR firstName:Ma*,15", // exact field-match
"lastName:\"van Es\",2", // exact field-match with space
"firstName:Mar*,6", // wildcard search
"firstName:N?ra,2", // wildcard search
"firstName:Mar* AND lastName:Spencer,1", // wildcard search
"email:martin.spencer@fa.hu,1", // email
"identification:\"df5521d7-b689-4ef5-9902-40b66b21eded\",1", // KeywordField
"identification:df5521d7*,1", // full wildcard on FieldName, partial wildcard on KeywordField
"gender:MALE,70" // ENUM
})
void testFieldSearch(String query, long expectedHits) throws ParseException {
Pageable pageable = PageRequest.of(0, 20);
SearchRequest<Customer> searchRequest = customerSearchRequestFactory.getSearchRequest(query, pageable, Customer.class);
Page<Customer> customers = customerSearchService.search(searchRequest);
assertThat(searchRequest.toString(), customers, is(notNullValue()));
assertThat(searchRequest.toString(), customers.getTotalElements(), is(expectedHits));
}
If i try to add search-strings for the “age” field (e.g. “age:6” or “age:[4 TO 72]”) the test fails because i get no hits.
At the heart of the SearchService i use:
...
private Page<T> runLuceneQuery(SearchRequest<T> searchRequest) throws ParseException {
log.debug("run LuceneQuery for: {}", searchRequest);
AtomicReference<SearchSession> searchSession = new AtomicReference<>(Search.session(entityManager));
QueryParser parser = new MultiFieldQueryParser(searchRequest.getFieldNames().toArray(new String[0]), new StandardAnalyzer());
Query query = parser.parse(searchRequest.getQuery());
SearchResult<T> result = searchSession.get().search(searchRequest.getEntityClass())
.extension(LuceneExtension.get())
.where(f -> f.fromLuceneQuery(query))
.fetch((int) searchRequest.getPageable().getOffset(), searchRequest.getPageable().getPageSize());
log.debug("results found: {}", result);
return getPage(searchRequest, result);
}
...
I am probably missing something very fundamental here, but what?
Any help is appreciated greatly.
Best regards
Jochen