diff --git a/README.md b/README.md index 2b40bbf..561b693 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,15 @@ Now install the API's dependencies by 'cd'-ing into the root of the repository a pnpm install ``` -Start your local database with `pnpm db:start`, `pnpm db:push` (if this is your first time) and then start the server with `pnpm dev` and it should work, assuming you have the correct env variables. (To see the contents of the database, I recommend using DBeaver. You can also run `pnpm db:studio` to start up drizzle studio) +Then start your local database with (assuming you have the correct env variables) + +```bash +pnpm db:start +pnpm db:push # if this is your first time running the db +pnpm dev +``` + +To see the contents of the database, I recommend using DBeaver. You can also run `pnpm db:studio` to start up drizzle studio ## Database schema changes (important!) diff --git a/src/db/dbQueryUtils.ts b/src/db/dbQueryUtils.ts index 9315a26..e48e52f 100644 --- a/src/db/dbQueryUtils.ts +++ b/src/db/dbQueryUtils.ts @@ -1,9 +1,11 @@ +import { avg, sql } from "drizzle-orm"; import { externalIdToInternalIdTable, emailTable, locationDataTable, overwritesTable, specialsTable, + starReviewTable, timeOverwritesTable, timesTable, weeklyTimeOverwritesTable, @@ -183,6 +185,19 @@ export class QueryUtils { return { idToPointOverrides, idToWeeklyOverrides }; } + async getRatingsAvgs() { + const ratingsAvgs = await this.db + .select({ + // only declares it to be a number, we explicitly cast it to a num + starRating: sql`cast(${avg(starReviewTable.starRating)} as decimal(2,1))`.mapWith(Number), + locationId: starReviewTable.locationId, + }) + .from(starReviewTable) + .groupBy(starReviewTable.locationId); + + return Object.fromEntries(ratingsAvgs.map((e) => [e.locationId, e.starRating])); + } + async getEmails(): Promise<{ name: string; email: string }[]> { const result = await this.db .select({ diff --git a/src/db/getLocations.ts b/src/db/getLocations.ts index f73046b..7ea4bff 100644 --- a/src/db/getLocations.ts +++ b/src/db/getLocations.ts @@ -22,6 +22,7 @@ export async function getAllLocationsFromDB(db: DBType, today: DateTime) { const { idToPointOverrides, idToWeeklyOverrides } = await DB.getTimeOverrides( timeSearchCutoff.toSQLDate(), ); + const ratingsAvgs = await DB.getRatingsAvgs(); // apply overrides, merge all time intervals, and add specials const finalLocationData = Object.entries(locationIdToData).map( @@ -43,6 +44,7 @@ export async function getAllLocationsFromDB(db: DBType, today: DateTime) { // time.end // ).toLocaleString()}` // ), + ratingsAvg: ratingsAvgs[id] ?? null, todaysSoups: specials[id]?.soups ?? [], todaysSpecials: specials[id]?.specials ?? [], }; diff --git a/src/endpoints/reviews.ts b/src/endpoints/reviews.ts index 7198609..c5b1120 100644 --- a/src/endpoints/reviews.ts +++ b/src/endpoints/reviews.ts @@ -40,7 +40,7 @@ reviewEndpoints buckets: t.Array(t.Number(), { example: [0, 1, 0, 4, 12, 4], description: - "Count of ratings of star rating [{.5},{1,1.5},{2,2.5},{3,3.5},{4,4.5},{5}", + "Count of ratings of star rating [{.5},{1,1.5},{2,2.5},{3,3.5},{4,4.5},{5}]", }), }), tagData: t.Array( diff --git a/src/endpoints/schemas.ts b/src/endpoints/schemas.ts index 6ccf14b..e053e4e 100644 --- a/src/endpoints/schemas.ts +++ b/src/endpoints/schemas.ts @@ -24,6 +24,7 @@ export const LocationSchema = t.Object({ name: t.Nullable(t.String({ examples: ["Schatz"] })), location: t.String(), + ratingsAvg: t.Nullable(t.Number()), shortDescription: t.Nullable(t.String()), description: t.String(), url: t.String(), diff --git a/tests/database.test.ts b/tests/database.test.ts index dbce728..78a5ef1 100644 --- a/tests/database.test.ts +++ b/tests/database.test.ts @@ -34,6 +34,7 @@ const locationIn: ILocation = { const locationOut = { id: "DYNAMICALLY GENERATED, replace with real id", name: "dbTest", + ratingsAvg: null, shortDescription: "hi", description: "description", url: "https://hi.com",