O que você precisa saber antes de começar
Prisma é uma ORM moderna para TypeScript e Node.js que simplifica o acesso ao banco de dados. Questões, no contexto do Prisma, geralmente se referem a modelos de dados criados para representar perguntas, respostas e quizzes em aplicações. Vou explicar como montar isso do zero, com um exemplo real que usei em um projeto recente.
Definindo o modelo no schema.prisma
A primeira coisa é criar o esquema. Abaixo está um exemplo básico de como modelar questões com Prisma:
model Questao {
id Int @id @default(autoincrement())
enunciado String
tipo TipoQuestao
opcoes Opcao[]
correta Int
disciplina String?
dificulade Dificulade @default(MEDIo)
createdAt DateTime @default(now())
}
enum TipoQuestao {
MULTIPLA_ESCOLA
VERDADEIRO_FALSO
}
enum Dificulade {
FACIL
MEDIo
DIFICIL
}
model Opcao {
id Int @id @default(autoincrement())
texto String
questaoId Int
questao Questao @relation(fields: [questaoId], references: [id])
}
prisma questoes na prática
Depois de definir o esquema, execute npx prisma migrate dev --name init para criar as tabelas no banco. Se estiver usando PostgreSQL, certifique-se de que a conexão esteja configurada corretamente no .env. Um problema comum que encontrei foi a relação entre Questao e Opcao. A princípio, pensei que poderia inserir as opções diretamente durante a criação da questão, mas o Prisma exige que a Questao já exista no banco para referenciar seu id. A solução foi fazer duas operações separadas:
const questao = await prisma.questao.create({
data: {
enunciado: "Qual a capital do Brasil?",
tipo: "MULTIPLA_ESCOLA",
dificulade: "FACIL",
opcoes: {
create: [
{ texto: "São Paulo", correta: false },
{ texto: "Brasília", correta: true },
{ texto: "Rio de Janeiro", correta: false },
]
}
},
include: { opcoes: true }
});
Isso resolve, mas preste atenção: se o banco já tiver dados, migrations podem causar conflitos. Use sempre npx prisma db seed para popular tabelas de forma controlada.
👉 Clique no botão abaixo para saber mais sobre o assunto!
Pegadinhas que ninguém conta
Uma coisa que os tutoriais não mostram é como lidar com questões de verdadeiro/falso quando você quer reutilizar o mesmo modelo. No início, eu criava campos separados para cada tipo de questão, o que gerava manutenção inviável. A solução mais limpa é usar um campo discriminador, como o enum TipoQuestao acima, e tratar a lógica no código da aplicação, não no banco. Outro ponto: a validação de respostas. Se você quer permitir múltiplas respostas corretas, o campo correta como Int não funciona. Nesse caso, mude para um booleano no modelo Opcao e filtre no código. Eu perdi cerca de 3 horas refatorando isso porque não tinha pensado no cenário desde o início.
Querying questões com eficiência
Para buscar questões por disciplina e dificuldade:
const questoes = await prisma.questao.findMany({
where: {
disciplina: "Matemática",
dificulade: "MEDIo"
},
include: { opcoes: true },
take: 10,
skip: 0
});
Isso gera uma query única com JOIN, o que é eficiente. Mas se o número de questões for grande, considere paginar com cursor em vez de offset para evitar perda de performance em páginas avançadas.
Quando o Prisma não é a melhor escolha
Se seu projeto precisa de queries extremamente complexas, com CTEs, window functions ou stored procedures pesados, o Prisma pode limitar você. Nesse caso, usar Prisma junto com Knex ou SQL puro para essas queries específicas é uma saída válida. Não adianta forçar uma solução que não cabe no modelo. Também vale lembrar que o Prisma não é ideal para apps com alta concorrência de escrita no mesmo registro. Se você tem muitos usuários atualizando as mesmas questões ao mesmo tempo, considere otimizações de locking ou migrar para uma abordagem diferente.
Resumo rápido
Montar questoes com Prisma é direto. Defina o schema, rode migrate, insira os dados com include ou relate, e faça queries com where e include. Fique atento aos limites do ORM e escolha a ferramenta certa para o problema certo. Se precisar de ajuda com algo específico, posso dar mais detalhes.