#Ideal schema for a textbook

8 messages · Page 1 of 1 (latest)

delicate ledge
#

Would this be the best way to declare the schema for a Textbook? Which of these fields should be made optional? Is there a good way to further modularize it>

import { defineSchema, defineTable } from "convex/server";
import { v } from "convex/values";

export default defineSchema({
  textbooks: defineTable({
    title: v.string(),
    description: v.string(),
    language: v.string(),
    chapters: v.array(v.object({
      chapterName: v.string(),
      chapterIndex: v.string(),
      chapterDescription: v.string(),
      sections: v.array(v.object({
        sectionName: v.string(),
        sectionIndex: v.string(),
        sectionDescription: v.string(),
      })),
    })),
  }),
});
paper mulchBOT
#

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

#

Your schema for a textbook looks well-structured and comprehensive. However, whether to make certain fields optional or not depends on your specific use case and the data you expect to have.

For instance, if there are textbooks that might not have a description, you could make the description field optional by wrapping it with v.optional(...). The same applies to other fields like chapterDescription and sectionDescription. Here's how you can do it:

import { defineSchema, defineTable } from "convex/server";
import { v } from "convex/values";

export default defineSchema({
  textbooks: defineTable({
    title: v.string(),
    description: v.optional(v.string()),
    language: v.string(),
    chapters: v.array(v.object({
      chapterName: v.string(),
      chapterIndex: v.string(),
      chapterDescription: v.optional(v.string()),
      sections: v.array(v.object({
        sectionName: v.string(),
        sectionIndex: v.string(),
        sectionDescription: v.optional(v.string()),
      })),
    })),
  }),
});

As for further modularizing your schema, you could define the chapter and section objects separately and then use them in your textbooks table. However, this depends on whether you want to reuse these objects in other parts of your schema or not.

Remember, the goal is to make your schema as clear and maintainable as possible. If you find that certain parts of your schema are being repeated, it might be a good idea to extract them into separate definitions.

For more information on writing schemas in Convex, you can refer to the official documentation (https://docs.convex.dev/database/schemas#writing-schemas).

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

#

@delicate ledge kapa.ai is still learning and improving, please let us know how it did by reacting below

delicate ledge
#

What would be the best way to ensure validity of the input before mutating the action table by adding an entry? How should those functions be organized after the user input is collected and the values are obtained for the fields? When should validation take place? @paper mulch

paper mulchBOT
#

Let me check the knowledge base for you. One moment! :books:

#

To ensure the validity of the input before mutating the action table, you can use argument validation for your endpoints. Convex provides a way to add validation to your queries, mutations, and actions using the zod helpers from the convex-helpers npm package.

Here's an example of how you can use zod for validation:

import { defineMutation } from 'convex/server';
import { z } from 'zod';

const inputSchema = z.object({
  title: z.string(),
  description: z.string().optional(),
  language: z.string(),
  chapters: z.array(z.object({
    chapterName: z.string(),
    chapterIndex: z.string(),
    chapterDescription: z.string().optional(),
    sections: z.array(z.object({
      sectionName: z.string(),
      sectionIndex: z.string(),
      sectionDescription: z.string().optional(),
    })),
  })),
});

export default defineMutation(inputSchema, async ({ db }, input) => {
  // your mutation logic here
});

In this example, inputSchema is a zod schema that matches the structure of your input. The defineMutation function takes this schema as its first argument, and it will automatically validate any input against this schema before running the mutation. If the input is invalid, the mutation will throw an error.

Validation should take place as soon as you receive the user input, before any processing or mutation happens. This way, you can catch any invalid input early and prevent it from causing issues down the line.

As for organizing your functions, it's generally a good idea to separate your validation logic from your business logic. This way, your business logic can assume that the input is valid, which can make it simpler and easier to reason about.