I have a few queries, that seems very large in terms of lines of code, and I was wondering if there is a better way to do this. This example is a get query from multiple tables to then end up returning one object with a lot of information:
export const get = query({
handler: async (ctx) => {
const identity = await ctx.auth.getUserIdentity()
if (!identity) {
throw new Error("Not authenticated")
}
const userId = identity.subject
const user = await ctx.db
.query("users")
.withIndex("by_user", (q) => q.eq("userId", userId))
.first()
if (!user) {
throw new Error("Unauthenticated")
}
const teamId = user.activeTeam as Id<"teams">
if (!teamId) {
throw new Error("User has no active team")
}
const [flows, pipelines] = await Promise.all([
ctx.db
.query("flows")
.withIndex("by_team", (q) => q.eq("teamId", teamId))
.collect(),
ctx.db
.query("pipelines")
.withIndex("by_team", (q) => q.eq("teamId", teamId))
.collect(),
])
const getStatuses = pipelines.map((pipeline) =>
ctx.db
.query("statuses")
.withIndex("by_pipeline", (q) => q.eq("pipelineId", pipeline._id))
.collect()
)
const getPriorities = pipelines.map((pipeline) =>
ctx.db
.query("priorities")
.withIndex("by_pipeline", (q) => q.eq("pipelineId", pipeline._id))
.collect()
)
const getTypes = pipelines.map((pipeline) =>
ctx.db
.query("types")
.withIndex("by_pipeline", (q) => q.eq("pipelineId", pipeline._id))
.collect()
)
const [statusesArray, prioritiesArray, typesArray] = await Promise.all([
Promise.all(getStatuses),
Promise.all(getPriorities),
Promise.all(getTypes),
])
const statuses = statusesArray.flat()
const priorities = prioritiesArray.flat()
const types = typesArray.flat()
const pipelineMap = new Map(pipelines.map((p) => [p._id, p]))
const statusMap = new Map(statuses.map((s) => [s._id, s]))
const priorityMap = new Map(priorities.map((p) => [p._id, p]))
const typeMap = new Map(types.map((t) => [t._id, t]))
const memberPromises = flows.map((flow) =>
ctx.db
.query("flowMembers")
.withIndex("by_flow", (q) => q.eq("flowId", flow._id as Id<"flows">))
.collect()
)
const flowMembers = await Promise.all(memberPromises)
const allUserIds = flowMembers.flat().map((member) => member.userId)
const uniqueUserIds = Array.from(new Set(allUserIds))
const userPromises = uniqueUserIds.map((userId) =>
ctx.db
.query("users")
.withIndex("by_id", (q) => q.eq("_id", userId as Id<"users">))
.first()
)
const users = await Promise.all(userPromises)
const userMap = new Map(
users.filter((user) => user !== null).map((user) => [user!._id, user!])
)
const flowsExtended = flows.map((flow, index) => {
const pipeline = pipelineMap.get(flow.pipelineId as Id<"pipelines">)
const status = statusMap.get(flow.statusId as Id<"statuses">)
const priority = priorityMap.get(flow.priorityId as Id<"priorities">)
const type = typeMap.get(flow.typeId as Id<"types">)
const members = flowMembers[index].map((member) =>
userMap.get(member.userId as Id<"users">)
)
return {
...flow,
pipeline: pipeline || null,
status: status || null,
priority: priority || null,
type: type || null,
members: members,
}
})
return flowsExtended
},
})
I heard about the query `convex-helpers/react` but I'm not sure if that can be of any help.