使用 ResultTransformer (DTO) 进行休眠搜索
Hibernate search with ResultTransformer (DTO)
我需要从Hibernate搜索结果中收集特定的DTO,我在maven中连接了所有的依赖,根据官方文档写了如下请求(我删除了不必要的代码,只能混淆,只剩下搜索需要什么):
public List<QuestionDto> search(String text) {
FullTextQuery query = fullTextEntityManager.createFullTextQuery(queryBuilder
.simpleQueryString()
.onField("description")
.matching(text)
.createQuery())
.setProjection("id", "description", "title", "countValuable", "persistDateTime", "user.fullName", "tags")
.setResultTransformer(new ResultTransformer() {
@Override
public Object transformTuple(Object[] tuple, String[] aliases) {
return QuestionDto.builder()
.id(((Number) tuple[0]).longValue())
.title((String) tuple[2])
.description((String) tuple[1])
.countValuable(((Number) tuple[3]).intValue())
.persistDateTime((LocalDateTime) tuple[4])
.username((String) tuple[5])
.tags((List<TagDto>) tuple[6])
.build();
}
@Override
public List transformList(List collection) {
return collection;
}
});
return query.getResultList();
}
但由于某些原因而不是标签出现 NULL
可能有人知道吗?
实体问题
@Indexed
public class Question {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Field(store = Store.YES)
private String title;
private Integer viewCount = 0;
@Field(store = Store.YES)
private String description;
@Field(store = Store.YES)
private LocalDateTime persistDateTime;
@Field(store = Store.YES)
private Integer countValuable = 0;
@ManyToOne(fetch = FetchType.LAZY, optional = false)
@IndexedEmbedded(includePaths = "fullName")
private User user;
@ManyToMany(fetch = FetchType.LAZY)
@IndexedEmbedded(includeEmbeddedObjectId = true, includePaths = {"name", "description"})
private List<Tag> tags;
实体标签
public class Tag {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Field(store = Store.YES)
private String name;
@Field(store = Store.YES)
private String description;
private LocalDateTime persistDateTime;
@ManyToMany(mappedBy = "tags", fetch = FetchType.LAZY)
@ContainedIn
private List<Question> questions;
这里有两个问题:
- 不支持多值字段的投影。
- 您正在尝试在 "object" 字段上投影:"tags" 本身没有值,它只有子字段("tags.name"、"tags.description" ).目前不支持 "object" 字段的投影。
如果您使用的是 Elasticsearch 后端,则可以利用 _source
投影 (org.hibernate.search.elasticsearch.ElasticsearchProjectionConstants#SOURCE
),它将 return Elasticsearch 文档的字符串表示形式,格式化作为 JSON。然后您可以解析它(例如使用 Gson)以提取您需要的任何信息。
当然,您始终可以选择完全不使用投影,然后从从数据库加载的实体中提取信息。
请注意,在 Hibernate Search 6(目前处于 Beta 阶段)中,我们将添加对 projections on multi-valued fields 的内置支持,但不太可能添加到处于维护模式的 Hibernate Search 5 (没有新功能或改进,只有错误修正)。
在更遥远的将来,我们可能会添加more direct support for DTOs。
我需要从Hibernate搜索结果中收集特定的DTO,我在maven中连接了所有的依赖,根据官方文档写了如下请求(我删除了不必要的代码,只能混淆,只剩下搜索需要什么):
public List<QuestionDto> search(String text) {
FullTextQuery query = fullTextEntityManager.createFullTextQuery(queryBuilder
.simpleQueryString()
.onField("description")
.matching(text)
.createQuery())
.setProjection("id", "description", "title", "countValuable", "persistDateTime", "user.fullName", "tags")
.setResultTransformer(new ResultTransformer() {
@Override
public Object transformTuple(Object[] tuple, String[] aliases) {
return QuestionDto.builder()
.id(((Number) tuple[0]).longValue())
.title((String) tuple[2])
.description((String) tuple[1])
.countValuable(((Number) tuple[3]).intValue())
.persistDateTime((LocalDateTime) tuple[4])
.username((String) tuple[5])
.tags((List<TagDto>) tuple[6])
.build();
}
@Override
public List transformList(List collection) {
return collection;
}
});
return query.getResultList();
}
但由于某些原因而不是标签出现 NULL 可能有人知道吗?
实体问题
@Indexed
public class Question {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Field(store = Store.YES)
private String title;
private Integer viewCount = 0;
@Field(store = Store.YES)
private String description;
@Field(store = Store.YES)
private LocalDateTime persistDateTime;
@Field(store = Store.YES)
private Integer countValuable = 0;
@ManyToOne(fetch = FetchType.LAZY, optional = false)
@IndexedEmbedded(includePaths = "fullName")
private User user;
@ManyToMany(fetch = FetchType.LAZY)
@IndexedEmbedded(includeEmbeddedObjectId = true, includePaths = {"name", "description"})
private List<Tag> tags;
实体标签
public class Tag {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Field(store = Store.YES)
private String name;
@Field(store = Store.YES)
private String description;
private LocalDateTime persistDateTime;
@ManyToMany(mappedBy = "tags", fetch = FetchType.LAZY)
@ContainedIn
private List<Question> questions;
这里有两个问题:
- 不支持多值字段的投影。
- 您正在尝试在 "object" 字段上投影:"tags" 本身没有值,它只有子字段("tags.name"、"tags.description" ).目前不支持 "object" 字段的投影。
如果您使用的是 Elasticsearch 后端,则可以利用 _source
投影 (org.hibernate.search.elasticsearch.ElasticsearchProjectionConstants#SOURCE
),它将 return Elasticsearch 文档的字符串表示形式,格式化作为 JSON。然后您可以解析它(例如使用 Gson)以提取您需要的任何信息。
当然,您始终可以选择完全不使用投影,然后从从数据库加载的实体中提取信息。
请注意,在 Hibernate Search 6(目前处于 Beta 阶段)中,我们将添加对 projections on multi-valued fields 的内置支持,但不太可能添加到处于维护模式的 Hibernate Search 5 (没有新功能或改进,只有错误修正)。
在更遥远的将来,我们可能会添加more direct support for DTOs。