Pre compute compatibility scores for faster profile lookup

This commit is contained in:
MartinBraquet
2025-11-26 22:49:33 +01:00
parent f97d24402e
commit aa35fa3b2b
17 changed files with 391 additions and 259 deletions

View File

@@ -273,8 +273,8 @@ export const API = (_apiTypeCheck = {
rateLimited: true,
props: z.object({userId: z.string()}),
returns: {} as {
profile: Profile
compatibleProfiles: Profile[]
// profile: Profile
// compatibleProfiles: Profile[]
profileCompatibilityScores: {
[userId: string]: CompatibilityScore
}
@@ -358,6 +358,9 @@ export const API = (_apiTypeCheck = {
props: z.object({
id: z.number(),
}),
returns: {} as {
status: 'success'
},
summary: 'Delete a compatibility answer',
tag: 'Compatibility',
},

View File

@@ -1,6 +1,6 @@
import { keyBy, sumBy } from 'lodash'
import { ProfileRow } from 'common/profiles/profile'
import { Row as rowFor } from 'common/supabase/utils'
import {keyBy, sumBy} from 'lodash'
import {ProfileRow} from 'common/profiles/profile'
import {Row as rowFor} from 'common/supabase/utils'
import {
areAgeCompatible,
areLocationCompatible,
@@ -24,15 +24,8 @@ export const getCompatibilityScore = (
answers1: rowFor<'compatibility_answers'>[],
answers2: rowFor<'compatibility_answers'>[]
): CompatibilityScore => {
const {
score: score1,
maxScore: maxScore1,
answerCount,
} = getAnswersCompatibility(answers1, answers2)
const { score: score2, maxScore: maxScore2 } = getAnswersCompatibility(
answers2,
answers1
)
const {score: score1, maxScore: maxScore1, answerCount} = getAnswersCompatibility(answers1, answers2)
const {score: score2, maxScore: maxScore2} = getAnswersCompatibility(answers2, answers1)
// >=100 answers in common leads to no weight toward 50%.
// Use sqrt for diminishing returns to answering more questions.
@@ -49,7 +42,7 @@ export const getCompatibilityScore = (
const confidence =
answerCount < 10 ? 'low' : answerCount < 100 ? 'medium' : 'high'
return { score: geometricMean, confidence }
return {score: geometricMean, confidence}
}
const getAnswersCompatibility = (
@@ -73,7 +66,7 @@ const getAnswersCompatibility = (
return getAnswerCompatibilityImportanceScore(a, answer2)
})
return { score, maxScore, answerCount }
return {score, maxScore, answerCount}
}
export function getAnswerCompatibilityImportanceScore(

View File

@@ -134,6 +134,7 @@ export type Database = {
compatibility_prompts: {
Row: {
answer_type: string
category: string | null
created_time: string
creator_id: string | null
id: number
@@ -143,6 +144,7 @@ export type Database = {
}
Insert: {
answer_type?: string
category?: string | null
created_time?: string
creator_id?: string | null
id?: number
@@ -152,6 +154,7 @@ export type Database = {
}
Update: {
answer_type?: string
category?: string | null
created_time?: string
creator_id?: string | null
id?: number
@@ -169,6 +172,48 @@ export type Database = {
},
]
}
compatibility_scores: {
Row: {
created_time: string
id: number
modified_time: string
score: number | null
user_id_1: string
user_id_2: string
}
Insert: {
created_time?: string
id?: never
modified_time?: string
score?: number | null
user_id_1: string
user_id_2: string
}
Update: {
created_time?: string
id?: never
modified_time?: string
score?: number | null
user_id_1?: string
user_id_2?: string
}
Relationships: [
{
foreignKeyName: 'compatibility_scores_user_id_1_fkey'
columns: ['user_id_1']
isOneToOne: false
referencedRelation: 'users'
referencedColumns: ['id']
},
{
foreignKeyName: 'compatibility_scores_user_id_2_fkey'
columns: ['user_id_2']
isOneToOne: false
referencedRelation: 'users'
referencedColumns: ['id']
},
]
}
contact: {
Row: {
content: Json | null