-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 posts ] 
Author Message
 Post subject: Indexing Problems with unidirectional indexEmbedded
PostPosted: Mon Sep 09, 2013 6:50 am 
Beginner
Beginner

Joined: Tue Nov 03, 2009 9:38 am
Posts: 24
We're using Hibernate Search 4.3 along with Hibernate 4.0.1 in a JBoss 7.0.1 environment and so far it all seems to work perfectly.
However, we're now facing some indexing problems which seem to originate from our search mapping.

I'll try and break down the problem into some abstract bits.

Consider the following entity structure:

We have 3 entities, 2 of which are indexed and one is part of the others' index.

Code:
class SharedEntity
{
  String key;
}

class IndexedEntityA
{
  SharedEntity s;
}

class IndexedEntityB
{
SharedEntity s;
}


Our SearchFactory is configured as follows:

Code:
SearchMapping mapping = new SearchMapping();

EntityMapping entityAMapping = mapping.entity( IndexedEntityA.class );
entityAMapping .indexed();
EntityMapping sharedMappingA = entityAMapping .property( "s", ElementType.FIELD ).indexEmbedded().targetElement( SharedEntity.class ).entity( SharedEntity.class );
sharedMappingA.property( "key", ElementType.FIELD ).field().store( Store.YES );

EntityMapping entityBMapping = mapping.entity( IndexedEntityB.class );
entityBMapping .indexed();
EntityMapping sharedMappingB = entityBMapping .property( "s", ElementType.FIELD ).indexEmbedded().targetElement( SharedEntity.class ).entity( SharedEntity.class );
sharedMappingB.property( "key", ElementType.FIELD ).field().store( Store.YES );


As you can see, SharedEntity is mapped twice, since it should be part of the indices for both IndexedEntityA and IndexedEntityB. But since there's no unique back reference there's no containedIn().

What puzzles me a bit is .entity( SharedEntity.class ); but without that, the entity mapping didn't seem to be found and thus was not mapped. Maybe that's a source of the problem, but I'm not sure about this.

So with this setup, whenever a SharedEntity is updated, Hibernate Search tries to update its index and doesn't find neither an index mapping (which is correct, since there's no explicit index for SharedEntity) nor a containedIn definition (which also seems to be correct, since there's no unique containedIn() ).

Thus, Hibernate Search throws the following exception:

Quote:
org.hibernate.search.SearchException: Unable to perform work. Entity Class is not @Indexed nor hosts @ContainedIn: class my.package.SharedEntity


I debugged into Hibernate Search and found the following spot within Hibernate Search's TransactionalWorker class:

Code:
public void performWork(Work<?> work, TransactionContext transactionContext) {
  final Class<?> entityType = instanceInitializer.getClassFromWork( work );
  EntityIndexBinder indexBindingForEntity = factory.getIndexBindingForEntity( entityType );
  if ( indexBindingForEntity == null
      && factory.getDocumentBuilderContainedEntity( entityType ) == null ) {
        throw new SearchException( "Unable to perform work. Entity Class is not @Indexed nor hosts @ContainedIn: " + entityType );
  }
  work = interceptWork( indexBindingForEntity, work );
  ...


The work is then passed to the PostTransactionWorkQueueSynchronization, but IMHO this shouldn't happen here (since SharedEntity instances should not be indexed in a standalone way).

indexBindingForEntity is null, which seems ok, because there is no index.
factory.getDocumentBuilderContainedEntity( entityType ) also returns null, which seems ok as well, since there is no contained entity definition (at least no unique one as seems to be the requirement).

I assume there's an error in the mapping, but I didn't find a solution yet.
Any ideas on this?


Top
 Profile  
 
 Post subject: Re: Indexing Problems with unidirectional indexEmbedded
PostPosted: Wed Sep 11, 2013 11:34 am 
Beginner
Beginner

Joined: Tue Nov 03, 2009 9:38 am
Posts: 24
Seems like I've found the problem.

First of all, I have to admit, that our model is a bit more complex, but I thought, that wouldn't matter (which seems to be wrong).

So here's an updated model:

Code:
class SharedEntity
{
  String key;
  Set<SharedEntityText> texts;
}

class SharedEntityText
{
  SharedEntity owner;
  String name;
}

class IndexedEntityA
{
  SharedEntity s;
}

class IndexedEntityB
{
SharedEntity s;
}


As you can see, the shared entity contains a set of text entities. Those have been mapped like this:

Code:
//expanding on my example above

EntityMapping sharedEntityTextMappingA = sharedMappingA.property( "texts", ElementType.FIELD ).indexEmbedded().targetElement( SharedEntityText.class ).entity( SharedEntityText.class );
   
//Here's the problem: this must not be defined
sharedEntityTextMappingA .property( "owner", ElementType.FIELD ).containedIn();

... //same for sharedMappingB


The problem now seems to be that whenever a SharedEntityText is changed Hibernate Search checks for the containedIn definition and if one is found, it starts its trek to the root entity. However, there is no way to reach it and thus the exception is thrown.

The solution thus would be to remove the containedIn definition from the embedded subtree whenever one of those definitions cannot be set, i.e. since containedIn cannot be set for SharedEntity, it should also not be set for any entities it embeds.

The documentation seems not to note this, so maybe one could add that bit of information. :)


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.