jabraJ
Convex Community10mo ago
40 replies
jabra

Hi All,

Hi All,

I would appreciate help on best practices how to do a paginate & join query or a preferred way to query efficiently, avoid unnecessary filtering and calls to loadMore on the frontend. I'm trying not to use collect() even when querying with indexes since I want to stuff to continue to scale.

I'm not tied to this design but I have 3 tables where

 schema is vary simple
members: (podId, userId)
pods: (superPodId, name, ....) with search index
superPods: (name, ....) 


// I need way effecient way to paginate the pods that the user is a member of
export const getMemberPods = query({
  args: {
    superPodId: v.id('superPods'),
    query: v.optional(
      v.object({
        name: v.optional(v.string()),
        categoryName: v.optional(v.string()),
      })
    ),
    paginationOpts: paginationOptsValidator,
  },
  handler: async (ctx, args) => {
    // get userId
    ...
  const podsQuery =
    query?.name && query.name !== ''
      ? ctx.db
          .query('pods')
          .withSearchIndex('search_name', (q) => q.search('name', query.name).eq('superPodId', superPodId))
      : ctx.db
          .query('pods')
          .withIndex('by_superPodId', (q) => q.eq('superPodId', superPodId))
          .order('desc')

  const paginatedPods = await podsQuery.paginate(paginationOpts);
  const memberPods = (
    await Promise.all(
      paginatedPods.page.map(async (pod) =>
        (await getMember(ctx, pod._id, userId)) ? pod : null
      )
    )
  ).filter((pod): pod is Doc<'pods'> => pod !== null);
  // post processing
  ....

    return { ...paginatedPods, page: memberPods }
}


// Helper function (member schema is userId, podId)
const getMember = async (ctx: QueryCtx, podId: Id<'pods'>, userId: Id<'users'>) => {
  return ctx.db
    .query('members')
    .withIndex('by_pod_id_user_id', (q) => q.eq('podId', podId).eq('userId', userId))
    .unique()
}



Thanks
Was this page helpful?