Index not directly indexed entity

Hi there,

i have a particular use-case where i need to index a child class witch is not declared @Indexed

@Indexed
class A {
   private String someproperty;
}

class B extends A {  <-- i try to update this
   
}

and i got this error :

Attempt to reindex an entity of type com.xxx.A because a contained 
entity was modified, but this entity type is not indexed directly. 
There is a bug in Hibernate Search, please report it.

Both class A and B can be saved, A is not abstract.
B doesn’t have any indexed field

do you have any idea ?

Hi Alexis,

Yoann will be back on Monday but in the meantime, here are some (maybe) useful information:

Could you try with Beta8 and if you can still reproduce the issue, could you come up with a small reproducer based on https://github.com/hibernate/hibernate-test-case-templates/tree/master/search .

Thanks!

Hi,

As Guillaume said, until Beta8 the @Indexed annotations wasn’t inherited, so if you’re on Beta7 or earlier, this might be the problem. Try adding @Indexed to class B?

That being said, I’d like to know how exactly you got this message? If you’re indeed attempting to index an entity of type B, then it’s not normal that you’re getting A in the message.
The test case templates currently use Hibernate Search 5, but I’ll upgrade them to 6 this morning (EDIT: here you go). If you could give details about what you’re doing exactly, or create a reproducer, that would be greatly appreciated.

Hello Yoann !

You are right ! The message was in fact releated to B entity. My Bad !

Attempt to reindex an entity of type com.xxx.B because a contained 
entity was modified, but this entity type is not indexed directly. 
There is a bug in Hibernate Search, please report it.

Since My class A is a parent with @Inheritance(strategy = InheritanceType.JOINED), i was expecting to have the indexation working when i trigger indexation on B in the A index.
But in fact, even with the Beta8 i got two separated indexes, so when i search into the A index i don’t find my B class.
It’s probably a misconception from me, but i was wondering to have “partial” indexes, but it’s not a “document” approach

Note : this happen in my case because i have a very specific context with and old part of my application (hibernate 3) who check changes on entities with an hibernate interceptors to trigger manual indexation on the new stack with hibernate 5.

My entities are “marked” as indexed with a simple boolean for Hibernate 3 interceptors, and in this case my B class triggers the indexation because the A class is really indexed :stuck_out_tongue: sooo … here i found my message

This could be a simple reproducer

SearchSession searchSession = Search.session((EntityManager) sessionFactory.getCurrentSession());
SearchIndexingPlan searchWritePlan = searchSession.indexingPlan();
searchWritePlan.addOrUpdate(....session.get(com.xxx.B.class, id));
searchWritePlan.execute();

This is expected. Hibernate Search creates one index per concrete type. In short the only “inheritance strategy” in Hibernate Search is the equivalent of TABLE_PER_CLASS (“index-per-class”, if you will). We might add another one day, but there are complicated corner cases and it’s not currently a priority. That’s generally not a problem, because you can simply search across multiple indexes.

If you search through the Hibernate Search DSL, using the code below, you will actually search both indexes and get results from A as well as B:

// .search( A.class ) targets A and all its indexed subclasses
List<A> hits = Search.session(session).search( A.class ) 
        .where( f -> f.match().field( "name" ).matching( "foo ) )
        .fetchHits( 20 );

If you search through custom REST requests to the Elasticsearch _search endpoint, then yes, you’ll have to target both index A and index B.
I assume you already have, somewhere, some code that defines which index to target for entity A. You just have to map A.class to both indexes (comma-separated, e.g. indexA,indexB) instead of just the index for A (indexA) and you should be good to go. To be clear, I mean the requests should be sent to elasticsearch.acme.com:9200/indexA,indexB/_search/.
Alternatively, you can manually define an index alias on your Elasticsearch cluster that targets both indexes, but I’m not sure that’s worth the trouble.

Yes it’s perfeclty clear, that’s exactly what i figured out after some digging last week ! :slight_smile:
thank you again for your time