[questions][chore] update to support location tb

pull/457/head
hpkoh 3 years ago
parent 373e249014
commit 0cfb063c7c

@ -0,0 +1,39 @@
/*
Warnings:
- You are about to drop the column `location` on the `QuestionsQuestionEncounter` table. All the data in the column will be lost.
*/
-- AlterTable
ALTER TABLE "QuestionsQuestionEncounter" DROP COLUMN "location",
ADD COLUMN "cityId" TEXT,
ADD COLUMN "countryId" TEXT,
ADD COLUMN "stateId" TEXT,
ALTER COLUMN "companyId" DROP NOT NULL;
-- CreateIndex
CREATE INDEX "QuestionsAnswer_updatedAt_id_idx" ON "QuestionsAnswer"("updatedAt", "id");
-- CreateIndex
CREATE INDEX "QuestionsAnswer_upvotes_id_idx" ON "QuestionsAnswer"("upvotes", "id");
-- CreateIndex
CREATE INDEX "QuestionsAnswerComment_updatedAt_id_idx" ON "QuestionsAnswerComment"("updatedAt", "id");
-- CreateIndex
CREATE INDEX "QuestionsAnswerComment_upvotes_id_idx" ON "QuestionsAnswerComment"("upvotes", "id");
-- CreateIndex
CREATE INDEX "QuestionsQuestionComment_updatedAt_id_idx" ON "QuestionsQuestionComment"("updatedAt", "id");
-- CreateIndex
CREATE INDEX "QuestionsQuestionComment_upvotes_id_idx" ON "QuestionsQuestionComment"("upvotes", "id");
-- AddForeignKey
ALTER TABLE "QuestionsQuestionEncounter" ADD CONSTRAINT "QuestionsQuestionEncounter_countryId_fkey" FOREIGN KEY ("countryId") REFERENCES "Country"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "QuestionsQuestionEncounter" ADD CONSTRAINT "QuestionsQuestionEncounter_stateId_fkey" FOREIGN KEY ("stateId") REFERENCES "State"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "QuestionsQuestionEncounter" ADD CONSTRAINT "QuestionsQuestionEncounter_cityId_fkey" FOREIGN KEY ("cityId") REFERENCES "City"("id") ON DELETE SET NULL ON UPDATE CASCADE;

@ -111,6 +111,7 @@ model Country {
name String @unique
code String @unique
states State[]
questionsQuestionEncounters QuestionsQuestionEncounter[]
}
model State {
@ -119,6 +120,7 @@ model State {
countryId String
cities City[]
country Country @relation(fields: [countryId], references: [id])
questionsQuestionEncounters QuestionsQuestionEncounter[]
@@unique([name, countryId])
}
@ -128,6 +130,7 @@ model City {
name String
stateId String
state State @relation(fields: [stateId], references: [id])
questionsQuestionEncounters QuestionsQuestionEncounter[]
@@unique([name, stateId])
}
@ -440,7 +443,7 @@ model QuestionsQuestion {
votes QuestionsQuestionVote[]
comments QuestionsQuestionComment[]
answers QuestionsAnswer[]
QuestionsListQuestionEntry QuestionsListQuestionEntry[]
questionsListQuestionEntries QuestionsListQuestionEntry[]
@@index([lastSeenAt, id])
@@index([upvotes, id])
@ -450,14 +453,18 @@ model QuestionsQuestionEncounter {
id String @id @default(cuid())
questionId String
userId String?
// TODO: sync with models (location, role)
companyId String
location String @db.Text
companyId String?
countryId String?
stateId String?
cityId String?
role String @db.Text
seenAt DateTime
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
country Country? @relation(fields: [countryId], references: [id], onDelete: SetNull)
state State? @relation(fields: [stateId], references: [id], onDelete: SetNull)
city City? @relation(fields: [cityId], references: [id], onDelete: SetNull)
company Company? @relation(fields: [companyId], references: [id], onDelete: SetNull)
user User? @relation(fields: [userId], references: [id], onDelete: SetNull)
question QuestionsQuestion @relation(fields: [questionId], references: [id], onDelete: Cascade)

@ -2,7 +2,7 @@ import { z } from 'zod';
import { createRouter } from '../context';
import type { AggregatedQuestionEncounter } from '~/types/questions';
import { createAggregatedQuestionEncounter } from '~/utils/questions/server/aggregate-encounters';
export const questionsQuestionEncounterRouter = createRouter().query(
'getAggregatedEncounters',
@ -21,41 +21,7 @@ export const questionsQuestionEncounterRouter = createRouter().query(
},
});
const companyCounts: Record<string, number> = {};
const locationCounts: Record<string, number> = {};
const roleCounts: Record<string, number> = {};
let latestSeenAt = questionEncountersData[0].seenAt;
for (let i = 0; i < questionEncountersData.length; i++) {
const encounter = questionEncountersData[i];
latestSeenAt =
latestSeenAt < encounter.seenAt ? encounter.seenAt : latestSeenAt;
if (!(encounter.company!.name in companyCounts)) {
companyCounts[encounter.company!.name] = 1;
}
companyCounts[encounter.company!.name] += 1;
if (!(encounter.location in locationCounts)) {
locationCounts[encounter.location] = 1;
}
locationCounts[encounter.location] += 1;
if (!(encounter.role in roleCounts)) {
roleCounts[encounter.role] = 1;
}
roleCounts[encounter.role] += 1;
}
const questionEncounter: AggregatedQuestionEncounter = {
companyCounts,
latestSeenAt,
locationCounts,
roleCounts,
};
return questionEncounter;
return createAggregatedQuestionEncounter(questionEncountersData);
},
},
);

@ -1,7 +1,6 @@
import { z } from 'zod';
import { TRPCError } from '@trpc/server';
import { createAggregatedQuestionEncounter } from '~/utils/questions/server/aggregate-encounters';
import { createProtectedRouter } from '../context';

@ -1,5 +1,6 @@
import { z } from 'zod';
import { QuestionsQuestionType } from '@prisma/client';
import { JobTitleLabels } from '~/components/shared/JobTitles';
import { TRPCError } from '@trpc/server';
import { createQuestionWithAggregateData } from '~/utils/questions/server/aggregate-encounters';
@ -11,13 +12,16 @@ import { SortOrder, SortType } from '~/types/questions.d';
export const questionsQuestionRouter = createRouter()
.query('getQuestionsByFilter', {
input: z.object({
companyNames: z.string().array(),
companyIds: z.string().array(),
cursor: z.string().nullish(),
endDate: z.date().default(new Date()),
limit: z.number().min(1).default(50),
countryIds: z.string().array(),
cityIds: z.string().array(),
stateIds: z.string().array(),
locations: z.string().array(),
questionTypes: z.nativeEnum(QuestionsQuestionType).array(),
roles: z.string().array(),
roles: z.nativeEnum(JobTitleLabels).array(),
sortOrder: z.nativeEnum(SortOrder),
sortType: z.nativeEnum(SortType),
startDate: z.date().optional(),
@ -56,7 +60,9 @@ export const questionsQuestionRouter = createRouter()
encounters: {
select: {
company: true,
location: true,
country: true,
city: true,
state: true,
role: true,
seenAt: true,
},
@ -84,11 +90,11 @@ export const questionsQuestionRouter = createRouter()
gte: input.startDate,
lte: input.endDate,
},
...(input.companyNames.length > 0
...(input.companyIds.length > 0
? {
company: {
name: {
in: input.companyNames,
id: {
in: input.companyIds,
},
},
}
@ -149,7 +155,9 @@ export const questionsQuestionRouter = createRouter()
encounters: {
select: {
company: true,
location: true,
country: true,
city: true,
state: true,
role: true,
seenAt: true,
},

@ -14,10 +14,20 @@ export type Question = {
user: string;
};
export type StateInfo = {
total: number;
cityCounts: Record<string, number>;
};
export type CountryInfo = {
total: number;
stateInfos: Record<string, StateInfo>;
};
export type AggregatedQuestionEncounter = {
companyCounts: Record<string, number>;
latestSeenAt: Date;
locationCounts: Record<string, number>;
countryCounts: Record<string, CountryInfo>;
roleCounts: Record<string, number>;
};

@ -1,15 +1,20 @@
import type {
City,
State,
Country,
Company,
QuestionsQuestion,
QuestionsQuestionVote,
} from '@prisma/client';
import { Vote } from '@prisma/client';
import type { AggregatedQuestionEncounter, Question } from '~/types/questions';
import type { AggregatedQuestionEncounter, Question, CountryInfo} from '~/types/questions';
type AggregatableEncounters = Array<{
company: Company | null;
location: string;
city: City | null;
country: Country | null;
state: State | null;
role: string;
seenAt: Date;
}>;
@ -67,8 +72,8 @@ export function createQuestionWithAggregateData(
export function createAggregatedQuestionEncounter(
encounters: AggregatableEncounters,
): AggregatedQuestionEncounter {
const countryCounts: Record<string, CountryInfo> = {};
const companyCounts: Record<string, number> = {};
const locationCounts: Record<string, number> = {};
const roleCounts: Record<string, number> = {};
let latestSeenAt = encounters[0].seenAt;
@ -77,15 +82,50 @@ export function createAggregatedQuestionEncounter(
latestSeenAt =
latestSeenAt < encounter.seenAt ? encounter.seenAt : latestSeenAt;
if (!(encounter.company!.name in companyCounts)) {
if (encounter.company !== null) {
if (!(encounter.company.name in companyCounts)) {
companyCounts[encounter.company!.name] = 0;
}
companyCounts[encounter.company!.name] += 1;
}
if (!(encounter.location in locationCounts)) {
locationCounts[encounter.location] = 0;
if (encounter.country !== null) {
if (!(encounter.country.name in countryCounts)) {
countryCounts[encounter.country.name] = {
total: 0,
stateInfos: {},
};
}
locationCounts[encounter.location] += 1;
const countryInfo = countryCounts[encounter.country.name];
countryInfo.total += 1;
const countryStateInfo = countryInfo.stateInfos;
if (encounter.state !== null) {
if (!(encounter.state.name in countryStateInfo)) {
countryStateInfo[encounter.state.name] = {
total: 0,
cityCounts: {},
};
}
const stateInfo = countryStateInfo[encounter.state.name];
stateInfo.total += 1;
const cityCounts = stateInfo.cityCounts;
if (encounter.city !== null) {
if (!(encounter.city.name in cityCounts)) {
cityCounts[encounter.city.name] = 0;
}
cityCounts[encounter.city.name] += 1;
}
}
}
if (!(encounter.role in roleCounts)) {
roleCounts[encounter.role] = 0;
@ -96,7 +136,7 @@ export function createAggregatedQuestionEncounter(
return {
companyCounts,
latestSeenAt,
locationCounts,
countryCounts,
roleCounts,
};
}

Loading…
Cancel
Save