#What is the idiomatic way to model many-to-many relationships in a convex schema

1 messages · Page 1 of 1 (latest)

grand lodge
#

I have many users which can join many groups. how would I model this in a schema?

restive sleetBOT
#

Hi @grand lodge. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:

#

The idiomatic way to model many-to-many relationships in Convex is to use a join table (also called a relationship or association table). In your case, where many users can join many groups, you would create a third table (e.g., groupUsers) that stores a reference to both a user and a group.

Here’s how you might define this in your Convex schema:

defineSchema({
  users: defineTable({
    // user fields
  }),
  groups: defineTable({
    // group fields
  }),
  groupUsers: defineTable({
    userId: v.id("users"),
    groupId: v.id("groups"),
    // Optionally, other fields like join date, role, etc.
  })
    .index("userId", ["userId"])      // To get groups for a user
    .index("groupId", ["groupId"]),   // To get users in a group
});

How it works:

  • Each document in groupUsers represents a single membership (a user in a group).
  • To find all groups a user is in, query groupUsers by userId.
  • To find all users in a group, query groupUsers by groupId.
  • You can add additional indexes (e.g., on both userId and groupId) for efficient lookups if needed.

Example: Adding a user to a group

await ctx.db.insert('groupUsers', { userId, groupId });

Example: Querying all users in a group

const groupUsers = await ctx.db.query("groupUsers")
  .withIndex("groupId", q => q.eq("groupId", group._id))
  .collect();
const userIds = groupUsers.map(gu => gu.userId);
const users = await Promise.all(userIds.map(db.get));
#

This approach is scalable and aligns with Convex best practices for handling many-to-many relationships, as it avoids the limitations of storing large arrays of IDs directly on user or group documents and allows for efficient querying in both directions Relationship Structures: Let's Talk About Schemas, Database Relationship Helpers.

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: