尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

Keystone 6 Multiselect 字段完整指南:类型、选项与 GraphQL 集成实战

发布时间:2026/9/24 17:22:05

资讯中心
01
ARTICLE

Keystone 6 Multiselect 字段完整指南:类型、选项与 GraphQL 集成实战

Keystone 6 Multiselect 字段完整指南:类型、选项与 GraphQL 集成实战
后端【免费下载链接】keystoneThe superpowered headless CMS for Node.js — built with GraphQL and React项目地址https://gitcode.com/gh_mirrors/key/keystone点击查看免费下载导读multiselect是 Keystone 内置的“多选”字段类型用于让一条记录从你预先定义的一组options中选择一个值的集合数组。它非常适合标签Tags、多分类、多权限标记等场景与单选的select字段互补。本文将基于 Keystone 源码与官方文档完整讲解 multiselect 的配置项、三种值类型string / enum / integer、数据库与 GraphQL 层的存储行为、Admin UI 的两种交互模式并结合仓库内的实现与测试用例给出可复制的实战配置。Multiselect 是什么根据 官方字段参考文档一个multiselect字段表示从定义的options中选取一组值。与单选的select字段不同值的类型可以是字符串string、整数integer或枚举enum由type选项决定type决定的是该字段在GraphQL API 中的数据类型与select不同type不会改变数据库类型——multiselect字段在数据库中始终以 JSON 数组存储Prisma 的Json标量。这一点可以在仓库中找到直接证据在 测试沙箱的 schema.prisma 中multiselect 字段被生成为multiselect Json default([])而在 测试沙箱的 schema.graphql 中对应的 GraphQL 输出类型为[String!]可空数组、元素非空。配置选项总览以下是 multiselect 支持的全部配置项源自官方文档并结合源码注释补充细节配置项默认值说明typestring字段值的类型必须是[string, enum, integer]之一options必填一个{ label, value }数组label是 Admin UI 中显示的文本value用于 GraphQL API 并存储到数据库defaultValue[]创建条目时未显式传值时使用的默认值db.map无为字段添加 Prismamap属性改变数据库中的列名graphql.read.isNonNullfalse在无读访问控制时可将输出字段设为非空graphql.create.isNonNullfalse在无创建访问控制时可将 create 输入字段设为非空并带默认值ui.displayModeselectAdmin UI 交互模式checkboxes复选框组或select组合框 标签db.isNullablefalse数据库层面是否可空db.extendPrismaSchema无用于扩展生成的 Prisma schema 字段定义说明ui.displayMode、db.isNullable与db.extendPrismaSchema在官方参考文档正文中没有展开但明确存在于 multiselect 字段源码类型定义 中本文一并纳入讲解。关于options的两种写法从 MultiselectFieldConfig 类型定义 可以看到options的写法取决于typetype为string或enum时options可以是{ label: string; value: string }对象数组也可以是纯字符串数组。当传入纯字符串时源码会调用humanize(option)自动生成展示用的 labelconfigToOptionsAndGraphQLTypetype为integer时options必须是{ label: string; value: number }数组且defaultValue相应地为数字数组。完整配置示例官方文档给出的最小可用配置如下它展示了type、options、defaultValue与db.map的组合用法import { config, list } from keystone-6/core; import { multiselect } from keystone-6/core/fields; export default config({ lists: { SomeListName: list({ fields: { someFieldName: multiselect({ type: enum, options: [ { label: ..., value: ... }, /* ... */ ], defaultValue: [...], db: { map: my_multiselect }, }), /* ... */ }, }), /* ... */ }, /* ... */ });一个更贴近实战的完整例子以“文章标签”为例把三种type的典型场景都展示出来便于直接复制修改import { config, list } from keystone-6/core; import { multiselect } from keystone-6/core/fields; export default config({ lists: { Post: list({ fields: { // 枚举类型value 只能是预定义枚举值GraphQL 层会生成独立的枚举类型 tags: multiselect({ type: enum, options: [ { label: News, value: news }, { label: Tutorial, value: tutorial }, { label: Release, value: release }, ], defaultValue: [news], ui: { displayMode: checkboxes }, }), // 字符串类型value 是自由字符串GraphQL 层是 [String!] categories: multiselect({ type: string, options: [ { label: 前端, value: frontend }, { label: 后端, value: backend }, ], }), // 整数类型value 是 32 位有符号整数GraphQL 层是 [Int!] priorityLevels: multiselect({ type: integer, options: [ { label: Level 1, value: 1 }, { label: Level 2, value: 2 }, { label: Level 3, value: 3 }, ], defaultValue: [1], db: { map: priority_levels }, }), }, }), }, });options的便捷简写如果你不关心 Admin UI 中显示的自定义 label可以直接传字符串数组源码会自动将字符串 humanize 为 label实现位置multiselect({ type: string, options: [red, green, blue], })三种值类型与 GraphQL 数据形态type决定 GraphQL 层的数据类型这在 configToOptionsAndGraphQLType 中实现type: stringGraphQL 类型为[String!]。value是任意字符串如a stringtype: integerGraphQL 类型为[Int!]。value必须是 32 位有符号整数范围内的数字-2147483648到2147483647。源码在 index.ts 中对此做了显式校验一旦发现value不是整数或超出范围会在启动时抛出TypeErrortype: enumGraphQL 层会为字段自动生成一个命名枚举类型其名称格式为${listKey}${FieldName}Type例如列表Post的字段tags会生成PostTagsType枚举值即各 option 的value生成逻辑。无论哪种type字段在 GraphQL 输出层都是元素非空的列表g.list(g.nonNull(...))index.ts。在数据库中则统一以 JSON 数组存储且默认值为[]sandbox schema.prisma。与select字段的关键差异从实现对比可以更清楚地理解 multiselect 的定位select字段在 Prisma 层使用String或Int标量见 select 字段源码是单值列multiselect字段在 Prisma 层固定使用Json标量index.ts存储的是整个数组。因此两者的type选项含义不同对select而言type影响数据库列类型而对multiselect而言type只影响 GraphQL 层的类型呈现。校验规则与源码级约束multiselect 内置了严格的运行时校验均在 字段实现 中可见选项去重所有 option 的value必须唯一否则启动时报错has duplicate options, this is not allowedindex.ts值必须在白名单内create/update 时传入数组中的每个值都必须是已定义 option 的value否则校验钩子抛出value is not an accepted optionindex.ts不允许重复选择同一字段的取值数组内不能有重复值否则抛出non-unique set of options selectedindex.ts不支持唯一索引isIndexed: unique不被支持配置后会直接抛出TypeErrorindex.ts。这些约束同样体现在测试矩阵中在 multiselect 测试夹具 中supportsUnique false、supportsNullInput false、nonNullableDefault true、supportsDbMap true意味着该字段不可唯一索引、不可传 null、默认非空、支持db.map。默认值defaultValue的两种语义defaultValue默认是空数组[]。需要注意它的作用范围与平台差异创建条目时若没有显式传值字段会使用defaultValue。这由 create 输入解析器resolveCreate保证当传入值为undefined时回退到defaultValueindex.tsPrisma 默认值在 PostgreSQL 等数据库上源码会给字段生成字面量默认值JSON.stringify(defaultValue ?? null)而在SQLite 上则不生成 Prisma 默认值index.ts因为 SQLite 的 Json 默认值由 create 输入逻辑管理db.isNullable会影响defaultValue的解析当字段不可空时defaultValue缺省为[]index.ts。测试夹具也印证了“未显式赋值时默认存储为空数组”的行为storedValues中未提供company字段的记录最终存储为company: []test-fixtures.ts。graphql.isNonNull 的使用前提graphql.read.isNonNull与graphql.create.isNonNull两个选项有严格的前提条件——只能在对应方向没有访问控制时启用graphql.read.isNonNull仅当你没有读访问控制且不打算未来添加时才可设为true。原因在官方文档中解释得很清楚一旦存在访问控制被拒绝访问时字段会返回null而非空字段收到null会引发错误并向上传播直到遇到可空字段为止——这会导致整个条目不可读甚至在items查询中所有条目都不可读。源码中 assertReadIsNonNullAllowed 也会在“字段未设置validation.isRequired/db.isNullable: false却开启非空读”时直接抛错graphql.create.isNonNull仅当你没有创建访问控制时才能设为true此时 create 输入字段在 GraphQL 层变为非空并带有默认值。如果存在创建访问控制用户无权创建该字段时条目会始终通过不了访问控制校验。简单归纳这两个选项是“性能/类型严谨性”优化前提是确认对应方向永远放行否则会破坏字段与条目的可读/可写性。Admin UI 的两种展示模式在 multiselect 的 Admin UI 视图 中字段支持两种ui.displayModeselect默认渲染为一个可过滤的组合框Combobox 已选标签组TagGroup。用户键入文字过滤候选点选后以标签形式展示标签可逐个移除最多展示两行maxRows{2}SelectModeField 实现checkboxes渲染为一个复选框组CheckboxGroup所有 option 平铺为复选框勾选即选中CheckboxesModeField 实现。列表页的单元格展示也有优化当选中项超过 3 个时只显示第一个标签并追加N more例如 “News, 4 more”避免表格过宽Cell 组件。Admin UI 内部统一把 option 的value转为字符串处理valuesToOptionsWithStringValues序列化回 API 时再按字段type用parseInt还原为整数controller 实现。这也是为什么type: integer的 option value 必须落在 32 位有符号整数范围内。测试验证与延伸阅读仓库为 multiselect 提供了完整的 API 测试矩阵enum / string / integer 三种类型全覆盖见 multiselect 测试夹具它定义了初始数据、期望存储值、exampleValue等可用于理解字段在各种操作创建、查询、过滤、更新下的期望行为。如果你正在对比选择字段类型建议同时阅读 select 字段参考文档 与 字段总览文档深入理解字段底层机制可阅读 multiselect 源码 以及 非空 GraphQL 校验逻辑。小结multiselect是 Keystone 处理“一对多的值集合”场景的首选字段它把类型约束string / enum / integer、选项白名单校验、JSON 数组存储与两套 Admin UI 交互模式封装在一个配置对象中。使用时牢记三个要点options的 value 必须唯一且整数类型下在 32 位有符号整数范围内defaultValue默认[]在 SQLite 上不生成 Prisma 层默认值graphql.*.isNonNull仅在确认无访问控制时才启用。理解这些细节后你就能在真实项目中安全、高效地使用 multiselect 建模标签、分类与多选属性。赞分享后端【免费下载链接】keystoneThe superpowered headless CMS for Node.js — built with GraphQL and React项目地址https://gitcode.com/gh_mirrors/key/keystone点击查看免费下载相关推荐Keystone 字段类型Field Types完全指南数据模型、通用选项与动态字段机制Keystone 字段类型Field Types完全指南数据模型、通用选项与动态字段机制 Keystone 的字段类型Field Types是构建数据后端Keystone与GraphQL Code Generator集成类型安全开发实践Keystone与GraphQL Code Generator集成类型安全开发实践 在现代Web开发中类型安全正成为提升代码质量和开发效率的关键实践。当使用后端Keystone Classic Boolean 字段类型完整指南存储、更新规则、校验与过滤Keystone Classic Boolean 字段类型完整指南存储、更新规则、校验与过滤 Boolean 是 Keystone ClassicNode.后端上一篇wezterm.GLOBAL 全局状态存储指南让配置重载不再丢失 Lua 变量下一篇MaaAssistantArknights 小工具全解析公招识别、干员识别、仓库识别、抽卡监控与活动小游戏创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。