OneToMany with intermediate table

Hello, I don’t seem to understand how to get index of two linked tables with intermediate one.
Here is my model:

Profile:

@Entity
@Indexed
public class Profile extends AbstractEntity {

  @Lob
  @Column(name = "first_name")
  @Field(termVector = TermVector.YES)
  String firstName;

  @Lob
  @Column(name = "last_name")
  @Field(termVector = TermVector.YES)
  String lastName;

  @OneToMany(mappedBy = "profile", cascade = CascadeType.ALL)
  @IndexedEmbedded(depth = 2, includePaths = {"speciality.name"})
  Set<ProfileSpeciality> specialities = new LinkedHashSet<>();

}

ProfileSpeciality:

@Entity
public class ProfileSpeciality implements Serializable {

  @EmbeddedId
  @IndexedEmbedded
  ProfileSpecialityId id = new ProfileSpecialityId();

  @ManyToOne
  @MapsId("profile_id")
  @JoinColumn(name = "profile_id", foreignKey = @ForeignKey(name = "profile_specialities_profile_fk"))
  @ContainedIn
  Profile profile;

  @ManyToOne
  @MapsId("speciality_id")
  @JoinColumn(name = "speciality_id", foreignKey = @ForeignKey(name = "profile_specialities_speciality_fk"))
  @ContainedIn
  @Field(name = "speciality")
  Speciality speciality;

  Integer priority;

And finally Speciality:

public class Speciality extends AbstractEntity {

  @Lob
  @Column
  @NaturalId
  @ContainedIn
  String name;

}

I want the index to be just for the Profile as the search will be around it, and I want to also index the related Specialities for that profile.
With the current code the error I get when I start the indexing is:

org.hibernate.search.exception.SearchException: HSEARCH000135: Unable to guess FieldBridge for speciality in model.Speciality

Any help is appreciated!
Thanks

There are at least two problems in your snippet.

First, putting @Field on the speciality property means you’re asking Hibernate Search to convert the “speciality” into the value of an index field. Since you defined the Speciality class yourself, Hibernate Search cannot possibly know how to do that. What you probably want instead is to ask Hibernate Search to embed all of the relevant fields of Speciality, which you will have to define yourself.

To do that, just use @IndexedEmbedded on the speciality property, and add @Field on the name property of Speciality. This will create a field specialities.speciality.name in the index of your Profile entity.

The other problem is the @ContainedIn on Speciality.name. @ContainedIn is supposed to be placed on the opposite side of an association, when @IndexedEmbedded is used on one side.
You need to add a property @OneToMany(mappedBy = "speciality") Set<ProfileSpeciality> profiles = new LinkedHashSet<>(); on your Speciality entity, and annotate it with @ContainedIn. That way, whenever the name changes, Hibernate Search will be able to retrieve all the corresponding profiles and reindex them.

1 Like

Thank you for your help and guidance - I really appreciate it!

I’ve made the changes that you suggested and I’ve also added a @ContainedIn in the ProfileSpecialities.profile - without it the index wasn’t updated.

So the path starts from Profile with @Indexed on the class and @IndexedEmbedded(depth = 2) on the specialities field, then in ProfileSpeciality we have @ContainedIn on the profile field and @IndexedEmbedded(depth = 2) on the speciality field and finally on Speciality we have @Field on name and @ContainedIn on profiles.