Migrating HS 5 to Hibernate Search 6

Made changes according to the HS 6


this field is having value in uuid and I don’t want to tokenize it.
So want a exact match in HS result set.

Wanted to know how to set the analyzer in HS6 for HS5 Analyzer set in here

Previously uses the DateBridge and LongBridges for corresponding data type for range queries
as below


wanted to know the alternative for that .
Ps: I had almost 200 test cases in HS5 code and now after all the migration even single Testcase is not succeeding and every time got null result.

That’s exactly what will happen when you use @GenericField.

I’d advise you to read the getting started guide first. This section in particular explains how to define analyzers in Hibernate Search 6, and how to assign them to fields.

Essentially:

  • Define analyzers by implementing LuceneAnalysisConfigurer and then setting the configuration property hibernate.search.backend.analysis.configurer to the fully-qualified name of your implementation class (e.g. com.mycompany.config.MyAnalysisConfigurer).
  • Assign analyzers to field by mapping them using @FullTextField (instead of @GenericField) and then setting @FullTextField(analyzer = "emailNgram").

Range queries will work out of the box without the need to use a string encoding type.

So essentially you should map the date like this:

@GenericField
private Date creationDate;

And then query like this:

Date before = ...;
Date after = ...;
List<MyEntity> hits = Search.session(session).search(MyEntity.class)
    .where(f -> f.range().field("creationDate").between(before, after))
    .fetchHits(20);

Yes Even I understood the same but in test cases its always returning null

You mean fetchHits( 20 ) returns null elements? That’s unexpected.

What is you query definition exactly? In particular, what does your call to .select() (if any) look like?

okay so i guess i got where is the issue.
@yrodiere as u told its working as expected.
however the scenario I was testing is somehow different.

Actually its working when we direct query that element
But If we query from parent Objects (as its a embedded property for other object)

This is parent object (SAGA here)

This is child object (one embedded object of SAGA)

So if I query like “ticketId” it is giving result (Class to query here is Ticket)
However if I query like “tickets.ticketId” its returning null (Class to query here is SaleSaga)

@yrodiere Any guess how to tackle this :upside_down_face:

Ok, that’s clearer, but what is null exactly? What is the code you use to generate your query? (.search(SaleSaga.class).select(...).where( ...).fetchHits(...))

its a complicated code as too many objects and condition however this is what I did inside that request.

SearchPredicate predicate = factory.match().field(field)
.matching(fromValue)
.toPredicate();
booleanJunction.must(predicate);

SearchPredicate boolPredicate = booleanJunction.toPredicate();
List results = null;
results = searchSession.search(scope)
.where(boolPredicate)
.fetchHits(20);

since only one argument passed in request and hence only one predicate is in the flow

This shouldn’t return null; worst case you should get an empty list. Is the list null? Does the list contain nulls?

ah yes result list is empty

Ok, well that’s something else entirely.

Something in your predicates isn’t matching. Without knowledge of your predicates and your data, I can’t tell you what is not matching.

One way you could debug this is by commenting out most conditions, then uncommenting them one by one, until you get no results. Then have a look at the last you uncommented, that’s probably the one that doesn’t work.

If necessary, you can have a look at what query is getting executed exactly; see this section of the documentation

Also, if you didn’t reindex after changing the mapping, then do it. I many cases, you must reindex your data after a change to the mapping.

Ah, and one more thing… when you update associations, you must update both sides. If for example you didn’t add the ticket to SaleSaga.tickets when it was created, then Hibernate Search will not be able to know that this ticket must be indexed-embedded inside this SaleSaga; it won’t be, and you won’t get any match.

No ! I am doing that
image
image

here is mapping in index at Elastic Search index console
image

and here is the result set

image

The same predicates are being used the only difference in both the cases is only this

And for when its working
image
ElasticsearchSearchQueryImpl[{“query”:{“bool”:{“must”:{“match”:{“ticketId”:{“query”:“77ef74ce-2a66-4fbb-a5f2-3d965c4e0a0b”}}},“minimum_should_match”:“0”}},“_source”:false}]

here is the query string when its not working
ElasticsearchSearchQueryImpl[{“query”:{“bool”:{“must”:{“match”:{“tickets.ticketId”:{“query”:“77ef74ce-2a66-4fbb-a5f2-3d965c4e0a0b”}}},“minimum_should_match”:“0”}},"_source":false}]

Well your result set isn’t empty. You have a list containing a SalesSaga right there.

yes correct but there is no records in tickets.
is there any chance that when I am saving the data the link is broken ?

Ok so we’re finally getting to your real problem…

I can see two explanations for this:

  1. The owning side of your association is Ticket.saleSaga, and you didn’t set that property before saving your ticket. In that case, the association was not persisted, and the result you’re getting reflects the content of the database. Like I said, you must set both sides of your associations. The problem is in how you saved your entity, and everything works well on the Hibernate Search side. Note that you most likely would have the same problem with Hibernate Search 5, since the problem is in how you used Hibernate ORM, not Hibernate Search.
  2. You’re accessing SaleSaga.tickets outside of your transaction or after you closed the session. That’s dodgy and certainly will never work correctly. You should use the DTO pattern to copy data to an object that’s no linked to the session before you transfer it to other components of your application (REST service, …).