如何在Drizzle ORM中区分问题与选项表的一对一和多对一关系?
解决方案
1. 更新表结构,添加关联字段
首先需要在两张表中补充外键字段,支撑一对一(正确选项)和多对一(错误选项)的关联逻辑:
import { pgTable, varchar, integer, foreignKey } from 'drizzle-orm/pg-core'; import { timestamps } from './your-timestamps-util'; // 替换为你的时间戳定义路径 export const QuestionTable = pgTable("questions", { id: integer().primaryKey().generatedAlwaysAsIdentity(), question: varchar().notNull(), correctOptionId: integer().references(() => OptionTable.id, { onDelete: 'cascade' }), // 关联正确选项的一对一外键 ...timestamps, }); export const OptionTable = pgTable("options", { id: integer().primaryKey().generatedAlwaysAsIdentity(), text: varchar().notNull(), value: varchar().notNull(), questionId: integer().references(() => QuestionTable.id, { onDelete: 'cascade' }), // 关联所属问题的多对一外键 ...timestamps, });
2. 配置关系(针对已知Bug的Workaround)
针对多关系场景下无法指定一对一关系名称的Bug,可通过手动绑定关联字段、显式定义关系名,结合过滤逻辑实现需求:
import { relations } from 'drizzle-orm'; // 问题表关系定义 export const questionRelations = relations(QuestionTable, ({ one, many }) => ({ // 一对一:正确选项 correctOption: one(OptionTable, { fields: [QuestionTable.correctOptionId], references: [OptionTable.id], relationName: 'question_correct_option', }), // 一对多:错误选项,通过过滤排除正确选项 incorrectOptions: many(OptionTable, { relationName: 'question_incorrect_options', filters: (option, question) => option.questionId.eq(question.id).and(option.id.ne(question.correctOptionId)) }) })); // 选项表关系定义 export const optionRelations = relations(OptionTable, ({ one }) => ({ // 多对一:所属问题(作为错误选项时的关联) question: one(QuestionTable, { fields: [OptionTable.questionId], references: [QuestionTable.id], relationName: 'question_incorrect_options' }), // 反向一对一:作为正确选项对应的问题 correctForQuestion: one(QuestionTable, { fields: [OptionTable.id], references: [QuestionTable.correctOptionId], relationName: 'question_correct_option' }) }));
3. 查询示例
查询问题及关联的正确/错误选项
import { db } from './your-db-connection'; const targetQuestion = await db.query.QuestionTable.findFirst({ where: (q) => q.id.eq(1), with: { correctOption: true, incorrectOptions: true } });
手动Join查询(规避关系定义Bug的备选方案)
如果自动关系查询出现异常,可直接用Join语法实现:
const questionWithOptions = await db.select({ question: QuestionTable, correctOption: OptionTable, incorrectOptions: OptionTable }) .from(QuestionTable) .leftJoin(OptionTable, QuestionTable.correctOptionId.eq(OptionTable.id)) .leftJoin(OptionTable, QuestionTable.id.eq(OptionTable.questionId).and(OptionTable.id.ne(QuestionTable.correctOptionId))) .where(QuestionTable.id.eq(1));
注意事项
- 确保双向关系的
relationName完全一致,避免Drizzle自动生成冲突名称 incorrectOptions的过滤逻辑确保只返回当前问题下的非正确选项- 若Bug导致一对一关系失效,优先使用手动Join的方式实现查询
内容的提问来源于stack exchange,提问作者frost2709
相关产品推荐
相关产品推荐

