Skip to content

Commit 4f3891f

Browse files
authored
fix: optimize member identity queries to use VALUES clause joins (#3820)
1 parent cd2abde commit 4f3891f

1 file changed

Lines changed: 58 additions & 44 deletions

File tree

  • services/libs/data-access-layer/src/member_identities

services/libs/data-access-layer/src/member_identities/index.ts

Lines changed: 58 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -227,49 +227,65 @@ export async function findAlreadyExistingVerifiedIdentities(
227227
return []
228228
}
229229

230-
const conditions: string[] = []
231-
const values: string[] = []
230+
const valuesClause = p.identities
231+
.map((_, i) => `($(platform_${i}), $(type_${i}), $(value_${i}))`)
232+
.join(', ')
232233

233-
p.identities.forEach((identity, index) => {
234-
conditions.push(`(mi.platform = $${index * 2 + 1} AND mi.value = $${index * 2 + 2})`)
235-
values.push(identity.platform, identity.value)
234+
const data: Record<string, string> = {}
235+
p.identities.forEach((identity, i) => {
236+
data[`platform_${i}`] = identity.platform
237+
data[`type_${i}`] = identity.type
238+
data[`value_${i}`] = identity.value.toLowerCase()
236239
})
237240

238-
const whereClause = `(${conditions.join(' OR ')})`
239-
240241
return qx.select(
241242
`
243+
with input_identities (platform, type, value_lower) as (
244+
values ${valuesClause}
245+
)
242246
select mi.*
243247
from "memberIdentities" mi
244-
where ${whereClause}
245-
and mi."deletedAt" is null
248+
inner join input_identities i
249+
on mi.platform = i.platform
250+
and mi.type = i.type
251+
and lower(mi.value) = i.value_lower
252+
where mi."deletedAt" is null
246253
`,
247-
values,
254+
data,
248255
)
249256
}
250257

251258
export async function findMembersByVerifiedEmails(
252259
qx: QueryExecutor,
253260
emails: string[],
254261
): Promise<Map<string, IDbMember>> {
255-
const data = {
262+
if (emails.length === 0) {
263+
return new Map()
264+
}
265+
266+
const valuesClause = emails.map((_, i) => `($(email_${i}))`).join(', ')
267+
268+
const data: Record<string, string> = {
256269
type: MemberIdentityType.EMAIL,
257-
emails: emails.map((e) => e.toLowerCase()),
258270
}
259271

272+
emails.forEach((email, i) => {
273+
data[`email_${i}`] = email.toLowerCase()
274+
})
275+
260276
const results = await qx.select(
261277
`
262-
with matching_identities as (
263-
select mi."memberId", mi.value
264-
from "memberIdentities" mi
265-
where mi.verified = true
266-
and mi.type = $(type)
267-
and lower(mi.value) in ($(emails:csv))
268-
and mi."deletedAt" is null
269-
limit ${emails.length}
278+
with input_emails (value_lower) as (
279+
values ${valuesClause}
270280
)
271281
select mi.value as "identityValue", ${MEMBER_SELECT_COLUMNS.map((c) => `m."${c}"`).join(', ')}
272-
from "members" m inner join matching_identities mi on m.id = mi."memberId"
282+
from "memberIdentities" mi
283+
inner join input_emails i on lower(mi.value) = i.value_lower
284+
inner join "members" m on m.id = mi."memberId"
285+
where mi.verified = true
286+
and mi.type = $(type)
287+
and mi."deletedAt" is null
288+
limit ${emails.length}
273289
`,
274290
data,
275291
)
@@ -287,38 +303,36 @@ export async function findMembersByVerifiedUsernames(
287303
qx: QueryExecutor,
288304
params: { segmentId: string; platform: string; username: string }[],
289305
): Promise<Map<{ platform: string; value: string }, IDbMember>> {
290-
const orConditions: string[] = []
291-
let index = 0
306+
if (params.length === 0) {
307+
return new Map()
308+
}
309+
310+
const valuesClause = params.map((_, i) => `($(platform_${i}), $(username_${i}))`).join(', ')
292311

293312
const data: Record<string, string> = {
294313
type: MemberIdentityType.USERNAME,
295314
}
296315

297-
for (const param of params) {
298-
const platformParam = `platform_${index++}`
299-
const usernameParam = `username_${index++}`
300-
301-
orConditions.push(
302-
`(mi.platform = $(${platformParam}) and lower(mi.value) = $(${usernameParam}))`,
303-
)
304-
305-
data[platformParam] = param.platform
306-
data[usernameParam] = param.username.toLowerCase()
307-
}
316+
params.forEach((param, i) => {
317+
data[`platform_${i}`] = param.platform
318+
data[`username_${i}`] = param.username.toLowerCase()
319+
})
308320

309321
const results = await qx.select(
310322
`
311-
with matching_identities as (
312-
select mi."memberId", mi.platform, mi.value
313-
from "memberIdentities" mi
314-
where mi.verified = true
315-
and mi.type = $(type)
316-
and mi."deletedAt" is null
317-
and (${orConditions.join(' or ')})
318-
limit ${params.length}
323+
with input_identities (platform, value_lower) as (
324+
values ${valuesClause}
319325
)
320326
select mi.platform as "identityPlatform", mi.value as "identityValue", ${MEMBER_SELECT_COLUMNS.map((c) => `m."${c}"`).join(', ')}
321-
from "members" m inner join matching_identities mi on m.id = mi."memberId"
327+
from "memberIdentities" mi
328+
inner join input_identities i
329+
on mi.platform = i.platform
330+
and lower(mi.value) = i.value_lower
331+
inner join "members" m on m.id = mi."memberId"
332+
where mi.verified = true
333+
and mi.type = $(type)
334+
and mi."deletedAt" is null
335+
limit ${params.length}
322336
`,
323337
data,
324338
)
@@ -364,7 +378,7 @@ export async function findMembersByIdentities(
364378
from "memberIdentities" mi
365379
inner join input_identities i
366380
on mi.platform = i.platform
367-
and mi.value = i.value
381+
and lower(mi.value) = lower(i.value)
368382
and mi.type = i.type
369383
and mi."deletedAt" is null
370384
where ${conditions.join(' and ')}

0 commit comments

Comments
 (0)