Hibernate 搜索子实体
Hiberate search for child entities
我有三个 classes 定义为:
1)类别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) 子类别 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) 页数 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;
}
现在数据定义如下:-
Category SubCategory Pages
-------- ------------ -------
Vehicle Car BMW
Electricals MotorCycle Hero
........... ........ Audi
........... ........ ......
Lapzz Laptop ......
Dell
现在我无法获取将使用休眠搜索在所有三个 class 中搜索的查询(即,如果我搜索 Lap*),我应该从类别、子类别和页面中获取结果,并且只有仅匹配查询的行不是 Category 的完整对象。
例如,当我搜索 Lap* 时,我应该在结果集中得到类别中包含 Lapzz 的行和子类别中包含 Laptop 的行。
请帮我找到这个解决方案。
据我了解,这应该可以满足您的要求:
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();
这里需要几个警告:
- 由于您使用的是ngram过滤器,查询时可能需要使用不同的分析器;参见
- 您在
Pages.subcategoryId
上的 @Field
注释非常可疑:分析数值没有意义。就此而言,将另一个实体的 ID 存储在 Pages
中是可疑的,您通常希望有一个类型为 SubCategory
的字段,并用 @ManyToOne
.[= 注释它28=]
- 如果您希望查询匹配描述中没有搜索词的类别,但包含名称或描述包含搜索词的页面,则必须添加 IndexedEmbedded并将嵌入字段(
"pages.pageName"
、"pages.pageDescription"
、...)添加到您的搜索查询中。
我有三个 classes 定义为:
1)类别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) 子类别 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) 页数 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;
}
现在数据定义如下:-
Category SubCategory Pages
-------- ------------ -------
Vehicle Car BMW
Electricals MotorCycle Hero
........... ........ Audi
........... ........ ......
Lapzz Laptop ......
Dell
现在我无法获取将使用休眠搜索在所有三个 class 中搜索的查询(即,如果我搜索 Lap*),我应该从类别、子类别和页面中获取结果,并且只有仅匹配查询的行不是 Category 的完整对象。
例如,当我搜索 Lap* 时,我应该在结果集中得到类别中包含 Lapzz 的行和子类别中包含 Laptop 的行。 请帮我找到这个解决方案。
据我了解,这应该可以满足您的要求:
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();
这里需要几个警告:
- 由于您使用的是ngram过滤器,查询时可能需要使用不同的分析器;参见
- 您在
Pages.subcategoryId
上的@Field
注释非常可疑:分析数值没有意义。就此而言,将另一个实体的 ID 存储在Pages
中是可疑的,您通常希望有一个类型为SubCategory
的字段,并用@ManyToOne
.[= 注释它28=] - 如果您希望查询匹配描述中没有搜索词的类别,但包含名称或描述包含搜索词的页面,则必须添加 IndexedEmbedded并将嵌入字段(
"pages.pageName"
、"pages.pageDescription"
、...)添加到您的搜索查询中。