diff --git a/src/libs/database/impl/Release.cpp b/src/libs/database/impl/Release.cpp index 4c2575c1..d06dad36 100644 --- a/src/libs/database/impl/Release.cpp +++ b/src/libs/database/impl/Release.cpp @@ -867,14 +867,11 @@ namespace lms::db for (const std::string& bindArg : where.getBindArgs()) query.bind(bindArg); - auto queryRes{ query.resultList() }; - std::map> clustersByType; - for (const Wt::Dbo::ptr& cluster : queryRes) - { + utils::forEachQueryResult(query, [&](const Wt::Dbo::ptr& cluster) { if (clustersByType[cluster->getType()->getId()].size() < size) clustersByType[cluster->getType()->getId()].push_back(cluster); - } + }); std::vector> res; for (const auto& [clusterTypeId, clusters] : clustersByType) @@ -882,4 +879,23 @@ namespace lms::db return res; } + + std::vector> Release::getClusters(ClusterTypeId clusterTypeId, std::size_t maxCount) const + { + assert(session()); + + auto query{ session()->query>("SELECT c FROM cluster c INNER JOIN track_cluster t_c ON t_c.cluster_id = c.id INNER JOIN track t ON t.id = t_c.track_id") + .where("t.release_id = ?").bind(getId()) + .where("c.cluster_type_id = ?").bind(clusterTypeId.toString()) + .groupBy("c.id") + .orderBy("COUNT(c.id) DESC") + .limit(static_cast(maxCount)) }; + + std::vector> res; + utils::forEachQueryResult(query, [&](const Wt::Dbo::ptr& cluster) { + res.push_back(cluster); + }); + + return res; + } } // namespace lms::db diff --git a/src/libs/database/include/database/Release.hpp b/src/libs/database/include/database/Release.hpp index f6df0773..885b9672 100644 --- a/src/libs/database/include/database/Release.hpp +++ b/src/libs/database/include/database/Release.hpp @@ -258,6 +258,7 @@ namespace lms::db // Each clusters are grouped by cluster type, sorted by the number of occurence (max to min) // size is the max number of cluster per cluster type std::vector>> getClusterGroups(const std::vector& clusterTypeIds, std::size_t size) const; + std::vector> getClusters(ClusterTypeId clusterTypeId, std::size_t maxCount) const; // Utility functions (if all tracks have the same values, which is legit to not be the case) core::PartialDateTime getDate() const; diff --git a/src/libs/subsonic/impl/responses/Album.cpp b/src/libs/subsonic/impl/responses/Album.cpp index eacefb0f..2344a18b 100644 --- a/src/libs/subsonic/impl/responses/Album.cpp +++ b/src/libs/subsonic/impl/responses/Album.cpp @@ -131,9 +131,9 @@ namespace lms::api::subsonic const ClusterType::pointer genreClusterType{ ClusterType::find(context.dbSession, "GENRE") }; if (genreClusterType) { - auto clusters{ release->getClusterGroups({ genreClusterType->getId() }, 1) }; - if (!clusters.empty() && !clusters.front().empty()) - albumNode.setAttribute("genre", clusters.front().front()->getName()); + const auto clusters{ release->getClusters(genreClusterType->getId(), 1) }; + if (!clusters.empty()) + albumNode.setAttribute("genre", clusters.front()->getName()); } if (const Wt::WDateTime dateTime{ core::Service::get()->getStarredDateTime(context.user->getId(), release->getId()) }; dateTime.isValid())