我想撰寫一個查詢,該查詢將獲取具有前 3 名最常聽曲目的藝術家頁面。是否可以通過單個存盤庫查詢來完成此操作?還是先創建一個查詢來獲取最受歡迎的藝術家,然后使用單獨的查詢為每個藝術家獲取前 3 個曲目會更好嗎?
最初我想用這樣的非本地查詢來完成它(它只按曲目獲取頂級流行藝術家并且不限制曲目):
@Query(value = "SELECT author FROM Artist artist JOIN artist.tracks track JOIN track.usersListenedTrack ult"
" WHERE ult.listenedAt >= :time"
" GROUP BY artist"
" ORDER BY COUNT(artist) DESC")
Page<Artist> findPopularArtistsByPeriod(Instant time, Pageable pageable);
但是因為非本機查詢不支持LIMIT運算子,我想我需要使用本機 sql(在我的情況下為 postgres)
因此,查詢應如下所示:
@Query(native = true, value = "SELECT * FROM artist a "
" INNER JOIN artist_tracks at ON at.artist_id = a.id"
" INNER JOIN tracks t ON at.track_id = t.id"
" INNER JOIN (SELECT * from listened_tracks lt WHERE ?????) tmp ON tmp.track_id = t.id"
" WHERE lt.listened_at >= :time"
" GROUP BY artist"
" ORDER BY COUNT(artist) DESC")
Page<Artist> findPopularArtistsByPeriod(Instant time, Pageable pageable);
但我不確定如何從listened_tracks按藝術家分組中選擇前 3 首曲目
所以,我的問題是:
- 可以在一個查詢中獲取此類資料嗎?
listened_tracks查詢表格以按藝術家獲取前 3 首曲目的正確方法是什么
uj5u.com熱心網友回復:
回答您的問題:
1 - 我認為可以在一個查詢中獲取這些資料。
2 - 您可以做到的一種方法是進行查詢以帶來您的頂級藝術家,然后在您的 Java 代碼中過濾前 3 名。另一種方法是將頁面的元素大小定義為 3,因為 `limit` 子句是hql 不支持。有一些方法可以比較 HQL 上的日期,例如,您可以使用 BETWEEN X AND Y 子句。
我在stackoverflow上找到了這篇關于限制結果的帖子,也許它可以幫助你!如何在 JPQL 或 HQL 中進行限制查詢?
uj5u.com熱心網友回復:
當每個藝術家的曲目數量很少時,只需選擇藝術家的頁面并獲取他們的所有曲目(直接作為第一個查詢的一部分,例如使用 join-fetch,或者使用第二個查詢獲取批次的軌道)。然后可以在 java 中輕松地對曲目進行排序和過濾。
但是,這也可能是一種真正的資源浪費,因為只需要 3 個最流行的曲目就可以丟棄大量曲目。
所以一般來說,應該考慮使用單個 DTO 投影查詢。
這里的問題是子集合的投影并不是那么簡單:
在 JPA DTO 投影查詢中加載子集合 DTO
將 JPA 或 Hibernate 投影查詢映射到 DTO(資料傳輸物件)
實作這一點的一種方便方法是使用blaze-persistance entity-views。它支持 DTO 的簡單定義和映射,包括collection-mappings。
DTO 可能如下所示:
@EntityView(ProjectionEntity.class) // <-- parent-entity
public interface ProjectionEntityView {
@IdMapping
Long getId();
// only include the 3 'most popular' children:
@Mapping(value = "children") // <-- associated collection
@Limit(limit = "3", order = { "counter DESC" }) // <-- each child has a 'counter' prop
List<ProjectionChildEntityView> getThe3MostPopularChildren(); // child-dto-projection
}
它可以通過 spring-data-repository 查詢:
public interface ProjectionEntityViewRepository
extends Repository<ProjectionEntity, Long> {
List<ProjectionEntityView> findAll(Pageable pageable);
}
擴展:假設您希望按藝術家的整體流行度(所有曲目的流行度總和)對藝術家進行排序,可以通過將相關子查詢指定為視圖界面的一部分,將此計算屬性包含到 DTO 中:
@EntityView(ProjectionEntity.class)
public interface ProjectionEntityView {
@IdMapping
Long getId();
@Mapping(value = "children")
@Limit(limit = "3", order = { "counter DESC" })
List<ProjectionChildEntityView> getThe3MostCountedChildren();
// "overall popularity of the artist"
@MappingSubquery(ChildrenCounterSumSubqueryProvider.class)
Long getCounterSum();
class ChildrenCounterSumSubqueryProvider implements SubqueryProvider {
@Override
public <T> T createSubquery(SubqueryInitiator<T> subqueryBuilder) {
return subqueryBuilder.from(ProjectionChildEntity.class, "child") //
.select("SUM(counter)") //
.where("child.parent.id").eqExpression("EMBEDDING_VIEW(id)")//
.groupBy("child.parent.id")
.end(); // (query-dsl is also possible)
}
}
}
然后可以Sort像往常一樣將計算的屬性作為 a 的一部分參考:
Pageable pageable = PageRequest.of(0, 10, Sort.by(Order.desc("counterSum"), Order.asc("id")));
var page1 = parentViewRepository.findAll(pageable);
帶測驗的完整示例
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/417588.html
標籤:
上一篇:如何從彩色矩形構建cv::Mat
