Skip to content

Commit

Permalink
Merge pull request #348 from quentinguidee/perfs/improve-get-best-songs
Browse files Browse the repository at this point in the history
Improve Songs/Artists/Albums query performances by ~50
  • Loading branch information
Yooooomi authored Feb 28, 2024
2 parents f46d56e + 12fec6d commit be61317
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 136 deletions.
140 changes: 4 additions & 136 deletions apps/server/src/database/queries/stats.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { InfosModel } from "../Models";
import { User } from "../schemas/user";
import {
basicMatch,
getBestInfos,
getGroupByDateProjection,
getGroupingByTimeSplit,
getTrackSumType,
Expand Down Expand Up @@ -557,156 +558,23 @@ export const getBestSongsNbOffseted = (
end: Date,
nb: number,
offset: number,
) =>
InfosModel.aggregate([
{ $match: basicMatch(user._id, start, end) },
{
$project: { ...getGroupByDateProjection(user.settings.timezone), id: 1 },
},
{
$lookup: lightTrackLookupPipeline(),
},
{ $unwind: "$track" },

// Adding the sum of the duration of all musics
{
$group: {
_id: null,
track: { $push: "$track" },
total_duration_ms: { $sum: "$track.duration_ms" },
total_count: { $sum: 1 },
},
},
{ $unwind: "$track" },
{
$group: {
_id: "$track.id",
track: { $last: "$track" },
total_count: { $last: "$total_count" },
total_duration_ms: { $last: "$total_duration_ms" },
duration_ms: { $sum: "$track.duration_ms" },
count: { $sum: 1 },
},
},
{ $sort: { count: -1, "track.name": 1 } },
{ $skip: offset },
{ $limit: nb },
{ $addFields: { "track.artist": { $first: "$track.artists" } } },
{
$lookup: lightAlbumLookupPipeline(),
},
{ $unwind: "$album" },
{
$lookup: lightArtistLookupPipeline(),
},
{ $unwind: "$artist" },
]);
) => getBestInfos("id", user, start, end, nb, offset);

export const getBestArtistsNbOffseted = (
user: User,
start: Date,
end: Date,
nb: number,
offset: number,
) =>
InfosModel.aggregate([
{ $match: basicMatch(user._id, start, end) },
{
$project: { ...getGroupByDateProjection(user.settings.timezone), id: 1 },
},
{
$lookup: lightTrackLookupPipeline(),
},
{ $unwind: "$track" },

// Adding the sum of the duration of all musics
{
$group: {
_id: null,
track: { $push: "$track" },
total_duration_ms: { $sum: "$track.duration_ms" },
total_count: { $sum: 1 },
},
},
{ $unwind: "$track" },
{ $addFields: { "track.artist": { $first: "$track.artists" } } },
{
$group: {
_id: "$track.artist",
track: { $last: "$track" },
total_count: { $last: "$total_count" },
total_duration_ms: { $last: "$total_duration_ms" },
duration_ms: { $sum: "$track.duration_ms" },
count: { $sum: 1 },
differents: { $addToSet: "$track.id" },
},
},
{ $addFields: { differents: { $size: "$differents" } } },
{ $sort: { count: -1, _id: 1 } },
{ $skip: offset },
{ $limit: nb },
{
$lookup: lightAlbumLookupPipeline(),
},
{ $unwind: "$album" },
{
$lookup: lightArtistLookupPipeline(),
},
{ $unwind: "$artist" },
]);
) => getBestInfos("primaryArtistId", user, start, end, nb, offset);

export const getBestAlbumsNbOffseted = (
user: User,
start: Date,
end: Date,
nb: number,
offset: number,
) =>
InfosModel.aggregate([
{ $match: basicMatch(user._id, start, end) },
{
$project: { ...getGroupByDateProjection(user.settings.timezone), id: 1 },
},
{
$lookup: lightTrackLookupPipeline(),
},
{ $unwind: "$track" },

// Adding the sum of the duration of all musics
{
$group: {
_id: null,
track: { $push: "$track" },
total_duration_ms: { $sum: "$track.duration_ms" },
total_count: { $sum: 1 },
},
},
{ $unwind: "$track" },
{ $addFields: { "track.artist": { $first: "$track.artists" } } },
{
$group: {
_id: "$track.album",
track: { $last: "$track" },
total_count: { $last: "$total_count" },
total_duration_ms: { $last: "$total_duration_ms" },
duration_ms: { $sum: "$track.duration_ms" },
count: { $sum: 1 },
differents: { $addToSet: "$track.id" },
},
},
{ $addFields: { differents: { $size: "$differents" } } },
{ $sort: { count: -1, _id: 1 } },
{ $skip: offset },
{ $limit: nb },
{
$lookup: lightAlbumLookupPipeline(),
},
{ $unwind: "$album" },
{
$lookup: lightArtistLookupPipeline(),
},
{ $unwind: "$artist" },
]);
) => getBestInfos("albumId", user, start, end, nb, offset);

export const getBestSongsOfHour = (user: User, start: Date, end: Date) => {
return InfosModel.aggregate([
Expand Down
66 changes: 66 additions & 0 deletions apps/server/src/database/queries/statsTools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { PipelineStage, Types } from "mongoose";
import { getWithDefault } from "../../tools/env";
import { Timesplit } from "../../tools/types";
import { User } from "../schemas/user";
import { InfosModel } from "../Models";

export const basicMatch = (
userId: string | Types.ObjectId,
Expand Down Expand Up @@ -182,3 +183,68 @@ export const lightArtistLookupPipeline = (
from: "artists",
as: "artist",
});

export const getBestInfos = (
idField: string,
user: User,
start: Date,
end: Date,
nb: number,
offset: number,
) =>
InfosModel.aggregate([
{ $match: basicMatch(user._id, start, end) },
{
$group: {
_id: `$${idField}`,
duration_ms: { $sum: "$durationMs" },
count: { $sum: 1 },
trackId: { $first: "$id" },
albumId: { $first: "$albumId" },
primaryArtistId: { $first: "$primaryArtistId" },
trackIds: { $addToSet: "$id" },
},
},
{ $addFields: { differents: { $size: "$trackIds" } } },
{
$facet: {
infos: [
{ $sort: { count: -1, _id: 1 } },
{ $skip: offset },
{ $limit: nb },
],
computations: [
{
$group: {
_id: null,
total_duration_ms: { $sum: "$duration_ms" },
total_count: { $sum: "$count" },
},
},
],
},
},
{ $unwind: "$infos" },
{ $unwind: "$computations" },
{
$project: {
_id: "$infos._id",
result: {
$mergeObjects: ["$infos", "$computations"],
},
},
},
{
$replaceRoot: {
newRoot: {
$mergeObjects: ["$result", { _id: "$_id" }],
},
},
},
{ $lookup: lightTrackLookupPipeline("trackId") },
{ $unwind: "$track" },
{ $lookup: lightAlbumLookupPipeline("albumId") },
{ $unwind: "$album" },
{ $lookup: lightArtistLookupPipeline("primaryArtistId", false) },
{ $unwind: "$artist" },
]);

0 comments on commit be61317

Please sign in to comment.