I'm trying to make a query with Hibernate Search. I would like to match a field that is in a Class extended from the parent (the child class is the @Indexed one).
Here is what i've done so far.
-Price is the indexed class-
@Indexed
@Table(name = "price_products")
public class PriceEntity extends AbstractPrice {
.....
.....
.....
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "productId")
private ECommerceProductEntity parent;
public ProductEntity getParent() {
return parent;
}
public void setParent(ProductEntity parent) {
this.parent = parent;
}
}
-Products is the parent class-
@Entity
@Indexed
@Table(name = "products")
public class ProductEntity extends AbstractProduct {
@OneToMany(mappedBy = "parent", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
private List<PriceEntity> prices;
/.others fields../
@Field(termVector = TermVector.YES)
@Size(max = 255)
private String tags;
/.others getter and setters../
public String getTags() {
return tags;
}
public void setTags(String tags) {
this.tags = tags;
}
public List<PriceEntity> getPrices() {
return prices;
}
public void setPrices(PriceEntity> prices) {
this.prices = prices;
}
public void addPrice(ECommercePriceEntity price) {
...
}
}
-AbstractProduct is extended by the products-
@MappedSuperclass
public abstract class AbstractProduct {
/.others fields../
@NotBlank
@Field(termVector = TermVector.YES)
private String description;
/getter end setters/
}
--Query--
FullTextEntityManager fullTextEntityManager
= Search.getFullTextEntityManager(entityManager);
fullTextEntityManager.createIndexer().startAndWait();
FullTextEntityManager fullTextEntityManager2
= Search.getFullTextEntityManager(entityManager);
QueryBuilder queryBuilder = fullTextEntityManager2.getSearchFactory()
.buildQueryBuilder()
.forEntity(PriceEntity.class)
.get();
Query myQuery = queryBuilder
.bool()
.should(queryBuilder.keyword().withConstantScore()
.onField("products.description").boostedTo(9l).matching(query)
.createQuery())
.should(queryBuilder.phrase().withConstantScore()
.onField("products.description").boostedTo(5l).sentence(query)
.createQuery())
.should(queryBuilder.keyword().withConstantScore()
.onField("products.tags").boostedTo(3l).matching(query)
.createQuery())
.should(queryBuilder.phrase().withConstantScore()
.onField("products.tags").boostedTo(1l).sentence(query)
.createQuery())
.createQuery();
org.hibernate.search.jpa.FullTextQuery jpaQuery
= fullTextEntityManager2.createFullTextQuery(myQuery, PriceEntity.class);
jpaQuery.setProjection("description");
List<PriceEntity> queryResults = jpaQuery.getResultList();
With the code above i get the following error
org.hibernate.search.exception.SearchException: Unable to find field products.description in ...
How to query by the fields "description" (in AbstractProduct) and tags in (ProductEntity) if the given entity to queryBuilder is PriceEntity?
Thanks in advance
You should use @IndexedEmbedded
.
@Indexed
@Table(name = "price_products")
public class PriceEntity extends AbstractPrice {
.....
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "productId")
@IndexedEmbedded // <= ADD THIS
private ECommerceProductEntity parent;
@Entity
@Indexed
@Table(name = "products")
public class ProductEntity extends AbstractProduct {
@OneToMany(mappedBy = "parent", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
@ContainedIn // <= ADD THIS
private List<PriceEntity> prices;
Then reindex all your data.
Then use the "parent." prefix when querying prices if you want to access product fields:
FullTextEntityManager fullTextEntityManager
= Search.getFullTextEntityManager(entityManager);
fullTextEntityManager.createIndexer().startAndWait();
FullTextEntityManager fullTextEntityManager2
= Search.getFullTextEntityManager(entityManager);
QueryBuilder queryBuilder = fullTextEntityManager2.getSearchFactory()
.buildQueryBuilder()
.forEntity(PriceEntity.class)
.get();
Query myQuery = queryBuilder
.bool()
.should(queryBuilder.keyword().withConstantScore()
.onField("parent.description").boostedTo(9l).matching(query)
.createQuery())
.should(queryBuilder.phrase().withConstantScore()
.onField("parent.description").boostedTo(5l).sentence(query)
.createQuery())
.should(queryBuilder.keyword().withConstantScore()
.onField("parent.tags").boostedTo(3l).matching(query)
.createQuery())
.should(queryBuilder.phrase().withConstantScore()
.onField("parent.tags").boostedTo(1l).sentence(query)
.createQuery())
.createQuery();
org.hibernate.search.jpa.FullTextQuery jpaQuery
= fullTextEntityManager2.createFullTextQuery(myQuery, PriceEntity.class);
jpaQuery.setProjection("parent.description");
List<PriceEntity> queryResults = jpaQuery.getResultList();