You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 12:47:19