关系字段上的 TypeORM SUM 运算符
TypeORM SUM Operator on Relation's field
我是一名学生,正在尝试开发音乐库以尝试新技术。
目前我使用 NestJS 和 TypeORM 作为我的后端技术(以及 MySQL 数据库)。
我想达到什么目的?我想获得播放列表的总持续时间。所以一个播放列表包含许多歌曲,歌曲可以出现在多个播放列表中。所以此时我们有一个多对多的关系。
现在为了获得 totalDuration,我认为使用某种 SUM 运算符是个好主意。这正是我的问题:我将如何使用 TypeORM 来做到这一点?
我尝试了以下查询生成器:
const playlist = await this.playlistRepository.createQueryBuilder("playlist")
.where("playlist.id = :playlistId", { playlistId })
// This is for relations
.leftJoinAndSelect("playlist.author", "author")
.leftJoinAndSelect("playlist.artwork", "artwork")
.leftJoinAndSelect("playlist.collaborators", "collaborators")
.leftJoin("playlist.songs", "songs")
// Counting the songs
.loadRelationCountAndMap("playlist.songsCount", "playlist.songs")
// SUM up the duration of every song to get total duration of the playlist
.addSelect('SUM(songs.duration)', 'totalDuration')
.groupBy("playlist.id")
.getOne()
但这给了我一个错误,我不知道如何解决:
QueryFailedError: Expression #16 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'soundcore_dev.collaborators.id' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
由 TypeORM 构建的结果查询如下所示:
SELECT
`playlist`.`id` AS `playlist_id`,
`playlist`.`createdAt` AS `playlist_createdAt`,
`playlist`.`authorId` AS `playlist_authorId`,
`playlist`.`artworkId` AS `playlist_artworkId`,
`author`.`id` AS `author_id`,
`artwork`.`id` AS `artwork_id`,
`collaborators`.`id` AS `collaborators_id`,
SUM(`songs`.`duration`) AS `totalDuration`
FROM
`sc_playlist` `playlist`
LEFT JOIN `sc_sso_user` `author` ON `author`.`id`=`playlist`.`authorId`
LEFT JOIN `sc_artwork` `artwork` ON `artwork`.`id`=`playlist`.`artworkId`
LEFT JOIN `sc_collaborators2playlist` `playlist_collaborators` ON `playlist_collaborators`.`playlistId`=`playlist`.`id`
LEFT JOIN `sc_sso_user` `collaborators` ON `collaborators`.`id`=`playlist_collaborators`.`ssoUserId`
LEFT JOIN `sc_song2playlist` `playlist_songs` ON `playlist_songs`.`playlistId`=`playlist`.`id`
LEFT JOIN `sc_song` `songs` ON `songs`.`id`=`playlist_songs`.`songId`
WHERE
`playlist`.`id` = ?
GROUP BY
`playlist`.`id`
我只做了一些研究,发现了如何使用 typeORM 进行总结,但我没有让它为我工作。上面的代码等等都是我找到的。我想我只是遗漏了一些非常重要的东西...
也许有人可以支持我。我真的很感激。
祝你有美好的一天!提前感谢您的支持。
阅读您的问题后,我不确定您为什么要加载所有关系并按播放列表 ID 对它们进行分组,
不管怎样,你首先要知道的是当我们想要得到 sum,max,avg,..
时,我们使用 getRawOne
或 getRawMany
对于您的查询,您只需要做:
const playlist = await this.playlistRepository.createQueryBuilder("playlist")
.where("playlist.id = :playlistId", { playlistId })
// This is for relations
.leftJoin("playlist.songs", "songs")
// Counting the songs
//.select('COUNT(songs.id)', 'numbersongs') in case you want count of songs
// SUM up the duration of every song to get total duration of the playlist
.addSelect('SUM(songs.duration)', 'totalDuration')
.getRawOne()
我是一名学生,正在尝试开发音乐库以尝试新技术。
目前我使用 NestJS 和 TypeORM 作为我的后端技术(以及 MySQL 数据库)。
我想达到什么目的?我想获得播放列表的总持续时间。所以一个播放列表包含许多歌曲,歌曲可以出现在多个播放列表中。所以此时我们有一个多对多的关系。 现在为了获得 totalDuration,我认为使用某种 SUM 运算符是个好主意。这正是我的问题:我将如何使用 TypeORM 来做到这一点?
我尝试了以下查询生成器:
const playlist = await this.playlistRepository.createQueryBuilder("playlist")
.where("playlist.id = :playlistId", { playlistId })
// This is for relations
.leftJoinAndSelect("playlist.author", "author")
.leftJoinAndSelect("playlist.artwork", "artwork")
.leftJoinAndSelect("playlist.collaborators", "collaborators")
.leftJoin("playlist.songs", "songs")
// Counting the songs
.loadRelationCountAndMap("playlist.songsCount", "playlist.songs")
// SUM up the duration of every song to get total duration of the playlist
.addSelect('SUM(songs.duration)', 'totalDuration')
.groupBy("playlist.id")
.getOne()
但这给了我一个错误,我不知道如何解决:
QueryFailedError: Expression #16 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'soundcore_dev.collaborators.id' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
由 TypeORM 构建的结果查询如下所示:
SELECT
`playlist`.`id` AS `playlist_id`,
`playlist`.`createdAt` AS `playlist_createdAt`,
`playlist`.`authorId` AS `playlist_authorId`,
`playlist`.`artworkId` AS `playlist_artworkId`,
`author`.`id` AS `author_id`,
`artwork`.`id` AS `artwork_id`,
`collaborators`.`id` AS `collaborators_id`,
SUM(`songs`.`duration`) AS `totalDuration`
FROM
`sc_playlist` `playlist`
LEFT JOIN `sc_sso_user` `author` ON `author`.`id`=`playlist`.`authorId`
LEFT JOIN `sc_artwork` `artwork` ON `artwork`.`id`=`playlist`.`artworkId`
LEFT JOIN `sc_collaborators2playlist` `playlist_collaborators` ON `playlist_collaborators`.`playlistId`=`playlist`.`id`
LEFT JOIN `sc_sso_user` `collaborators` ON `collaborators`.`id`=`playlist_collaborators`.`ssoUserId`
LEFT JOIN `sc_song2playlist` `playlist_songs` ON `playlist_songs`.`playlistId`=`playlist`.`id`
LEFT JOIN `sc_song` `songs` ON `songs`.`id`=`playlist_songs`.`songId`
WHERE
`playlist`.`id` = ?
GROUP BY
`playlist`.`id`
我只做了一些研究,发现了如何使用 typeORM 进行总结,但我没有让它为我工作。上面的代码等等都是我找到的。我想我只是遗漏了一些非常重要的东西...
也许有人可以支持我。我真的很感激。 祝你有美好的一天!提前感谢您的支持。
阅读您的问题后,我不确定您为什么要加载所有关系并按播放列表 ID 对它们进行分组,
不管怎样,你首先要知道的是当我们想要得到 sum,max,avg,..
时,我们使用 getRawOne
或 getRawMany
对于您的查询,您只需要做:
const playlist = await this.playlistRepository.createQueryBuilder("playlist")
.where("playlist.id = :playlistId", { playlistId })
// This is for relations
.leftJoin("playlist.songs", "songs")
// Counting the songs
//.select('COUNT(songs.id)', 'numbersongs') in case you want count of songs
// SUM up the duration of every song to get total duration of the playlist
.addSelect('SUM(songs.duration)', 'totalDuration')
.getRawOne()