Sometimes it might not be feasible to store data in an index, yet that data is necessary for filtering the search results. So I'm wondering what tricks or techniques could be used. Lets take the following example:
Code:
@Entity
@Indexed
public class Profile {
@Id
public int id;
@Field
public String name;
@OneToMany(mappedBy = "profile")
public Set<FavouritesMap> favouritesMap = new HashSet<FavouritesMap>();
}
@Entity
public class FavouritesMap {
@EmbeddedId
public FavouritesMapId id;
@ManyToOne
@JoinColumn(insertable = false, updatable = false)
public Profile profile;
@ManyToOne
@JoinColumn(insertable = false, updatable = false)
public User user;
}
@Embeddable
public class FavouritesMapId {
@Field
public int userId;
public int profileId;
}
Say we want to search our Profiles index, but filter the results by a specific user's favourite profiles. It's not feasible to have Profiles::favouritesMap stored in the index (ie via @IndexedEmbedded) as the collection could potentially have millions of records which would have a severe performance impact whenever a re-indexing operation took place.
My current workaround for this is essentially to do an SQL query to fetch the users favourite profiles first, and then add a restriction to the hibernate search query based on the return IDs.
Code:
Query q = em.createNativeQuery("SELECT p.id FROM Profile p JOIN FavouritesMap f ON f.id.profileId = p.id WHERE f.id.userId = X ");
List<Integer> favouriteIds = q.getResultList();
List<Query> favouritePredicates = new ArrayList<>();
for (Integer id : favouriteIds) {
favouritePredicates.add(qb.keyword().onFields("id").matching(id).createQuery());
}
mustQuery.add(combineShouldQuery(qb, favouritePredicates));
This is still not ideal as we could have ptentially 1000s of favourites to filter through. So I'm wondering if there are any other options to try?