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

如何在Nexus GraphQL关系字段的mutation中阻止/忽略指定字段被提交

你可以通过以下三种方式实现需求,可根据业务场景选择:

方案1:直接在crud mutation配置中使用computedInputs处理嵌套字段

和你单独创建帖子时的处理逻辑一致,直接在createUser的配置中添加嵌套字段校验逻辑,既可以抛出错误也可以直接忽略/覆盖用户传入的isPublished值:

const UserMutation = extendType({
  type: "Mutation",
  definition(t) {
    t.crud.createOneUser({
      alias: "createUser",
      inputs: {
        posts: {
          relateBy: "create",
        },
      },
      computedInputs: {
        posts: ({ args }) => {
          const postCreateData = args.data.posts?.create
          if (!postCreateData) return args.data.posts

          // 兼容单条/批量创建帖子的场景
          const formatPost = (post) => {
            // 如果要抛出错误打开下面两行注释
            // if ('isPublished' in post) {
            //   throw new Error("创建关联帖子时不允许手动设置isPublished字段")
            // }
            // 直接删除用户传入的isPublished字段,强制设置默认值
            delete post.isPublished
            return { ...post, isPublished: false }
          }

          return {
            create: Array.isArray(postCreateData) 
              ? postCreateData.map(formatPost) 
              : formatPost(postCreateData)
          }
        }
      }
    });
  },
});

方案2:自定义输入类型,从根上移除isPublished字段

直接定义关联创建时的Post输入类型,不暴露isPublished字段,客户端在请求阶段就会因为类型校验不通过无法传入该字段,安全性最高:

// 定义不带isPublished的帖子创建输入类型
const PostCreateWithoutUserInput = inputObjectType({
  name: "PostCreateWithoutUserInput",
  definition(t) {
    t.nonNull.string("content")
    // 不定义isPublished字段,客户端就无法传入
  }
})

// 定义用户创建输入类型,关联上面的帖子输入类型
const UserWithPostsCreateInput = inputObjectType({
  name: "UserWithPostsCreateInput",
  definition(t) {
    t.nonNull.string("name")
    t.nonNull.string("email")
    t.list.field("posts", { type: PostCreateWithoutUserInput })
  }
})

// 自定义mutation实现创建逻辑
const UserMutation = extendType({
  type: "Mutation",
  definition(t) {
    t.field("createUser", {
      type: "User",
      args: {
        data: nonNull(UserWithPostsCreateInput)
      },
      resolve: async (_, { data }, { prisma }) => {
        return prisma.user.create({
          data: {
            name: data.name,
            email: data.email,
            posts: {
              create: data.posts.map(post => ({
                ...post,
                isPublished: false // 强制设置默认值
              }))
            }
          }
        })
      }
    })
  }
})

方案3:使用Prisma中间件全局拦截校验

如果有多处需要关联创建帖子的场景,可以直接用Prisma中间件做全局校验,不用每个mutation单独写逻辑:

// 初始化Prisma后添加中间件
const prisma = new PrismaClient()

prisma.$use(async (params, next) => {
  // 拦截所有用户创建操作
  if (params.model === "User" && params.action === "create") {
    const postCreateList = params.args.data.posts?.create
    if (!postCreateList) return next(params)

    const posts = Array.isArray(postCreateList) ? postCreateList : [postCreateList]
    posts.forEach(post => {
      if ("isPublished" in post) {
        throw new Error("不允许手动设置帖子发布状态")
        // 需要忽略的话直接执行 delete post.isPublished 即可
      }
      post.isPublished = false
    })
  }
  return next(params)
})

内容的提问来源于stack exchange,提问作者user1945290

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 15:57:00