Suppose I'm building a grocery store app. I have several types, some of which are related and some which are not, e.g., Produce
, Fruit
, Apple
, Vegetable
, Asparagus
, Meat
, Chicken
, etc.
All of these types are associated with a collection of Tag
s in a M:N relationship. Each entity listed above can have multiple Tag
s, and each Tag
can be associated with many entities, of various types.
How would I best describe this relationship? Should each type hierarchy have a corresponding Tag
hierarchy? Using one common Tag
type works with plain vanilla JPA/Hibernate, but when introducing Hibernate Search, it wants both sides of the relationship described (e.g., using @ManyToMany(mappedBy = ...)
). How could I accomplish this?
====================== EXAMPLE ========================
Fruit:
@Data
@Entity
@Indexed
public class Fruit {
@Id
@GeneratedValue
private Long id;
@FullTextSearch
private String name;
@ManyToMany
@IndexedEmbedded
private Collection<Tag> tags;
}
Chicken:
@Data
@Entity
@Indexed
public class Chicken {
@Id
@GeneratedValue
private Long id;
@FullTextSearch
private String brand;
@ManyToMany
@IndexedEmbedded
private Collection<Tag> tags;
}
Tag:
@Data
@Entity
@Indexed
public class Tag {
@Id
@GeneratedValue
private Long id;
@FullTextSearch
private String name;
}
Hibernate Search needs to have an inverse mapping on the Tag
side to be able to automatically reindex any of Produce
, Fruit
, Apple
, Vegetable
, Asparagus
, Meat
, Chicken
etc. whenever a corresponding Tag
is changed and it would affect the index.
To do so you'd need to modify your Tag
entity to something like:
@Data
@Entity
@Indexed
public class Tag {
@Id
@GeneratedValue
private Long id;
@FullTextSearch
private String name;
@ManyToMany(mappedBy = "tags")
private List<Fruit> fruits;
@ManyToMany(mappedBy = "tags")
private List<Chicken> chickens;
// and so on ...
}
If your tags do not change their names after they've been saved, which would mean that you wouldn't have any changes to tags that would affect fruit/chicken/.../apple indexes you can mark your tag collections with @IndexingDependency(reindexOnUpdate = ReindexOnUpdate.SHALLOW)
. This will result in fruit/chicken/.../apple indexes being not updated whenever a tag assigned to any of the entities in those indexes is changed.
@Data
@Entity
@Indexed
public class Fruit {
@Id
@GeneratedValue
private Long id;
@FullTextSearch
private String name;
@ManyToMany
@IndexedEmbedded
@IndexingDependency(reindexOnUpdate = ReindexOnUpdate.SHALLOW)
private Collection<Tag> tags;
}
In that case you do not need to modify your Tag
entity, which doesn't need to model the inverse side of associations:
@Data
@Entity
@Indexed
public class Tag {
@Id
@GeneratedValue
private Long id;
@FullTextSearch
private String name;
// No inverse side of associations!
}
Please refer to this section in the documentation for a more detailed explanation on shallow indexing.