diff --git a/server/routes.ts b/server/routes.ts index ed360e8..8cc74ee 100644 --- a/server/routes.ts +++ b/server/routes.ts @@ -261,7 +261,8 @@ export async function registerRoutes( app.get("/api/articles/popular", async (req, res) => { const limit = parseInt(req.query.limit as string) || 6; - const articles = await storage.getPopularArticles(limit); + const days = parseInt(req.query.days as string) || 7; + const articles = await storage.getPopularArticles(limit, days); res.json(articles); }); diff --git a/server/storage.ts b/server/storage.ts index fdca954..d4bbe23 100644 --- a/server/storage.ts +++ b/server/storage.ts @@ -1,6 +1,6 @@ import { type Article, type InsertArticle, articles, articleViews, type InsertPushSubscription, type PushSubscription, pushSubscriptions } from "@shared/schema"; import { db } from "./db"; -import { eq, desc, sql, count, and } from "drizzle-orm"; +import { eq, desc, sql, count, and, gte, inArray } from "drizzle-orm"; import crypto from "crypto"; export interface IStorage { @@ -40,8 +40,33 @@ export class DatabaseStorage implements IStorage { return db.select().from(articles).orderBy(desc(articles.publishedAt)).limit(9); } - async getPopularArticles(limit: number): Promise { - return db.select().from(articles).orderBy(desc(articles.views)).limit(limit); + // "Beliebt" mora dejansko rotirati: steje ogled v zadnjih `days` dneh, ne + // stevec od zacetka. Ta je namrec za stare uspesnice tako visok, da se blok + // nikoli ne premakne. Ce svezih ogledov ni dovolj, dopolnimo po skupnem stevcu. + async getPopularArticles(limit: number, days: number = 7): Promise { + const since = new Date(Date.now() - days * 86400000); + const recent = await db + .select({ id: articleViews.articleId, n: count() }) + .from(articleViews) + .where(gte(articleViews.viewedAt, since)) + .groupBy(articleViews.articleId) + .orderBy(desc(count())) + .limit(limit * 3); + const ids = recent.map((r) => r.id); + let out: Article[] = []; + if (ids.length) { + const rows = await db.select().from(articles).where(inArray(articles.id, ids)); + const byId = new Map(rows.map((a) => [a.id, a])); + out = ids.map((i) => byId.get(i)).filter(Boolean) as Article[]; + } + if (out.length < limit) { + const fill = await db.select().from(articles).orderBy(desc(articles.views)).limit(limit * 2); + const have = new Set(out.map((a) => a.id)); + for (const a of fill) { + if (!have.has(a.id)) { out.push(a); have.add(a.id); } + } + } + return out.slice(0, limit); } async getArticlesByCategory(category: string): Promise {