I have three classes defined as:
1)Category class:-
@Entity
@Table(name = "CATEGORY")
@Data
@NoArgsConstructor
@AllArgsConstructor
@Indexed
public class Category {
@Id
@GeneratedValue
private Long id;
@Field(index = Index.YES, store = Store.YES, analyzer = @Analyzer(definition = "ngram"))
private String categoryName;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinColumn(name = "categoryId", referencedColumnName = "id")
@LazyCollection(LazyCollectionOption.TRUE)
@IndexedEmbedded
private List<SubCategory> subCategories;
private Long creationTime;
private Long updationTime;
}
2) SubCategory class:-
@Entity
@Table(name = "SUB_CATEGORY")
@Data
@NoArgsConstructor
@AllArgsConstructor
@Indexed
public class SubCategory {
@Id
@GeneratedValue
private Long id;
@Field(index = Index.YES,store = Store.YES,analyzer = @Analyzer(definition = "ngram1"))
private String subCategoryName;
@Field(index = Index.YES,store = Store.YES)
private Long categoryId;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinColumn(name = "subCategoryId", referencedColumnName = "id")
@LazyCollection(LazyCollectionOption.TRUE)
@IndexedEmbedded
private List<Pages> pages;
private Long creationTime;
}
3) Pages class:-
@Entity
@Table(name = "PAGES")
@Data
@NoArgsConstructor
@AllArgsConstructor
@Indexed
public class Pages {
@Id
@GeneratedValue
private Long id;
@Field(index = Index.YES,store = Store.YES,analyzer = @Analyzer(definition = "ngram2"))
private String pageName;
@Field(index = Index.YES,store = Store.YES,analyzer = @Analyzer(definition = "ngram2"))
private String pageDescription;
@Field(index = Index.YES,store = Store.YES,analyzer = @Analyzer(definition = "ngram2"))
private Long subCategoryId;
private Long creationTime;
}
Now the data is defined like:-
Category SubCategory Pages
-------- ------------ -------
Vehicle Car BMW
Electricals MotorCycle Hero
........... ........ Audi
........... ........ ......
Lapzz Laptop ......
Dell
Now I am stuck at getting the query that will search in all three classes using hibernate search(i.e.-If I search Lap*) I should get result from Categories,Subcategories and Pages and only the rows matching the query only not the complete object of Category.
eg-I should get in the result set the row containing Lapzz in categories and row containing Laptop in subcategories when I search for Lap*. Please help my find this solution.
This should do what you want, as far as I understand:
String searchTerms = ...;
QueryBuilder categoryQb = fullTextEntityManager.getSearchFactory().buildQueryBuilder().forEntity( Category.class ).get();
QueryBuilder subCategoryQb = fullTextEntityManager.getSearchFactory().buildQueryBuilder().forEntity( SubCategory.class ).get();
QueryBuilder pagesQb = fullTextEntityManager.getSearchFactory().buildQueryBuilder().forEntity( Pages.class ).get();
Query categoryQuery = categoryQb.keyword()
.onField( "categoryName" )
.matching( searchTerms )
.createQuery();
Query subCategoryQuery = subCategoryQb.keyword()
.onField( "subCategoryName" )
.matching( searchTerms )
.createQuery();
Query pagesQuery = pagesQb.keyword()
.onFields(
"pageName",
"pageDescription"
)
.matching( searchTerms )
.createQuery();
Query luceneQuery = categoryQb.bool()
.should( categoryQuery )
.should( subCategoryQuery )
.should( pagesQuery )
.createQuery();
FullTextQuery fullTextQuery = fullTextEntityManager.createFullTextQuery(
luceneQuery,
Category.class, SubCategory.class, Pages.class
);
List<?> results = fullTextQuery.getResultList();
Several warnings are necessary here:
@Field
annotation on Pages.subcategoryId
is highly suspicious: it doesn't make sense to analyze a numeric value. For that matter, it's suspicious to store the ID of another entity in Pages
, you'd generally want to have a field whose type is SubCategory
instead and annotate it with @ManyToOne
."pages.pageName"
, "pages.pageDescription"
, ...) to your search queries.