blok Beliebt: po ogledih zadnjih 7 dni namesto skupnega stevca, da se dejansko menja (parameter ?days=)
This commit is contained in:
+2
-1
@@ -261,7 +261,8 @@ export async function registerRoutes(
|
|||||||
|
|
||||||
app.get("/api/articles/popular", async (req, res) => {
|
app.get("/api/articles/popular", async (req, res) => {
|
||||||
const limit = parseInt(req.query.limit as string) || 6;
|
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);
|
res.json(articles);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
+28
-3
@@ -1,6 +1,6 @@
|
|||||||
import { type Article, type InsertArticle, articles, articleViews, type InsertPushSubscription, type PushSubscription, pushSubscriptions } from "@shared/schema";
|
import { type Article, type InsertArticle, articles, articleViews, type InsertPushSubscription, type PushSubscription, pushSubscriptions } from "@shared/schema";
|
||||||
import { db } from "./db";
|
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";
|
import crypto from "crypto";
|
||||||
|
|
||||||
export interface IStorage {
|
export interface IStorage {
|
||||||
@@ -40,8 +40,33 @@ export class DatabaseStorage implements IStorage {
|
|||||||
return db.select().from(articles).orderBy(desc(articles.publishedAt)).limit(9);
|
return db.select().from(articles).orderBy(desc(articles.publishedAt)).limit(9);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getPopularArticles(limit: number): Promise<Article[]> {
|
// "Beliebt" mora dejansko rotirati: steje ogled v zadnjih `days` dneh, ne
|
||||||
return db.select().from(articles).orderBy(desc(articles.views)).limit(limit);
|
// 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<Article[]> {
|
||||||
|
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<Article[]> {
|
async getArticlesByCategory(category: string): Promise<Article[]> {
|
||||||
|
|||||||
Reference in New Issue
Block a user