c21157fc93
New lib/recipe-ratings.ts helper batches avg score + review count for a set of recipe ids in one grouped query, kept separate from the main paginated/sorted search query rather than joining+grouping it directly (would've forced grouping by every selected column). Wired into /api/v1/search and the Explore page's trending/recent queries; SearchResultCard renders the star only when a recipe has at least one rating. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
21 lines
815 B
TypeScript
21 lines
815 B
TypeScript
import { db, ratings, inArray, sql } from "@epicure/db";
|
|
|
|
export type RatingSummary = { avgRating: number; ratingCount: number };
|
|
|
|
/** Average score + review count per recipe, for a batch of recipe ids — used to show rating stars on list/search cards without a per-row join. */
|
|
export async function getAvgRatingsByRecipeId(recipeIds: string[]): Promise<Map<string, RatingSummary>> {
|
|
if (recipeIds.length === 0) return new Map();
|
|
|
|
const rows = await db
|
|
.select({
|
|
recipeId: ratings.recipeId,
|
|
avgScore: sql<number>`avg(${ratings.score})::float`,
|
|
count: sql<number>`count(*)::int`,
|
|
})
|
|
.from(ratings)
|
|
.where(inArray(ratings.recipeId, recipeIds))
|
|
.groupBy(ratings.recipeId);
|
|
|
|
return new Map(rows.map((r) => [r.recipeId, { avgRating: r.avgScore, ratingCount: r.count }]));
|
|
}
|