feat(30-01): add popular-items-by-tags query to discovery service

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-12 20:41:03 +02:00
parent d37e64e71c
commit 2347d49b69

View File

@@ -1,6 +1,14 @@
import { and, count, desc, eq, isNotNull, lt, sql } from "drizzle-orm"; import { and, count, desc, eq, inArray, isNotNull, lt, sql } from "drizzle-orm";
import { db as prodDb } from "../../db/index.ts"; import { db as prodDb } from "../../db/index.ts";
import { globalItems, setupItems, setups, users } from "../../db/schema.ts"; import {
globalItemTags,
globalItems,
items,
setupItems,
setups,
tags,
users,
} from "../../db/schema.ts";
type Db = typeof prodDb; type Db = typeof prodDb;
@@ -125,3 +133,53 @@ export async function getTrendingCategories(
itemCount: r.itemCount, itemCount: r.itemCount,
})); }));
} }
/**
* Get popular global items filtered by tag names, ordered by owner count descending.
* Owner count = number of user items linked to each global item via globalItemId.
*/
export async function getPopularItemsByTags(
db: Db = prodDb,
tagNames: string[],
limit = 24,
): Promise<
Array<{
id: number;
brand: string | null;
model: string;
category: string | null;
weightGrams: number | null;
priceCents: number | null;
imageFilename: string | null;
description: string | null;
ownerCount: number;
}>
> {
if (tagNames.length === 0) return [];
const rows = await db
.select({
id: globalItems.id,
brand: globalItems.brand,
model: globalItems.model,
category: globalItems.category,
weightGrams: globalItems.weightGrams,
priceCents: globalItems.priceCents,
imageFilename: globalItems.imageFilename,
description: globalItems.description,
ownerCount: sql<number>`CAST(COUNT(DISTINCT ${items.id}) AS INT)`,
})
.from(globalItems)
.innerJoin(globalItemTags, eq(globalItemTags.globalItemId, globalItems.id))
.innerJoin(tags, eq(tags.id, globalItemTags.tagId))
.leftJoin(items, eq(items.globalItemId, globalItems.id))
.where(inArray(tags.name, tagNames))
.groupBy(globalItems.id)
.orderBy(
desc(sql<number>`COUNT(DISTINCT ${items.id})`),
desc(globalItems.id),
)
.limit(limit);
return rows;
}