Grafast 标准步骤first从数组与迭代器中取首元素的高性能实现【免费下载链接】crystal Graphiles Crystal Monorepo; home to Grafast, PostGraphile, pg-introspection, pg-sql2 and much more!项目地址: https://gitcode.com/gh_mirrors/cry/crystal导读first是 GrafastGraphile Crystal 仓库中的核心执行引擎提供的标准步骤standard step它的职责非常简单取得某个列表步骤list plan所产出数组中的第一项。本文围绕grafast/website/grafast/standard-steps/first.md展开结合grafast/grafast/src/steps/first.ts的完整实现讲解first的两种调用形态数组优化路径与通用迭代器路径、它的类型约束、底层执行语义以及它在dataplan-pg、ConnectionStep等真实模块中的落地用法。读完后你将能准确判断何时该用first、何时应显式传false并理解它在计划优化optimize阶段如何被化简为直接依赖。一、first的作用与两种调用形态按官方文档定义first步骤会“产出给定步骤所产出数组中的第一项”Yields the first entry in the array the given step yields。核心 API 在 grafast/grafast/src/steps/first.ts 中导出export function firstTData( plan: StepRepresentingListTData, array true, ): FirstStepTData { return plan.operationPlan.cacheStep( plan, GrafastInternal:first(), array, () new FirstStep(plan, array), ); }1.1 默认形态数组优化array true文档给出的最典型用法是const $firstItem first($array);当第二个参数省略默认true时Grafast 认为传入的步骤代表的是一个数组或null/undefined从而启用更激进的优化路径——见下文unbatchedExecute与optimalExecute两条快路径。1.2 通用形态迭代器/异步迭代器array false文档明确指出如果传入的参数是异步迭代器需要显式传false以关闭数组优化// If the argument is an iterable, pass false to opt out of the array // optimizations const $firstItem first($iterable, false);这背后的原因在构造函数first.ts中一目了然constructor(parentPlan: StepRepresentingListTData, isArray true) { super(); this.addStrongDependency(itemsOrStep(parentPlan)); if (isArray) { this.unbatchedExecute unbatchedExecute; this.execute optimalExecuteTData; this.isSyncAndSafe true; } else { this.isSyncAndSafe false; } }isArray true直接替换为极简的同步执行器并把isSyncAndSafe置为true允许 Grafast 在同步上下文安全复用结果。isArray false放弃同步安全保证执行期需要真正遍历迭代器才能取出首项。二、类型约束StepRepresentingListfirst的第一个参数类型是StepRepresentingListTData定义于 grafast/grafast/src/steps/connection.tsexport type StepRepresentingList TItem, TNodeStep extends Step StepTItem, TEdgeStep extends EdgeCapableStepTItem, TNodeStep EdgeStepTItem, TNodeStep, TCursorValue string, | ConnectionOptimizedStepTItem, TNodeStep, TEdgeStep, TCursorValue | StepWithItemsTItem | StepMaybereadonly TItem[];也就是说first不仅接受普通的“产出数组的步骤”也接受经过游标优化cursor-optimized的连接步骤ConnectionOptimizedStep带有items()访问器的步骤StepWithItems即可以显式取到元素列表的步骤直接产出readonly TItem[]允许为null/undefined的步骤。构造函数内部通过itemsOrStep(parentPlan)定义于同一文件的 connection.ts把“连接类步骤”统一归一为“元素列表步骤”再建立强依赖addStrongDependency确保上游列表先于first执行完毕。三、执行语义数组快路径与迭代器兜底FirstStep的执行逻辑分两层first.ts 与 first.ts。3.1 非批处理快路径function unbatchedExecute(_extra: UnbatchedExecutionExtra, list: any[]) { return list?.[0]; }非批处理unbatched模式下直接取list[0]若列表为空或为null?.保证结果是undefined而不是抛错。3.2 批处理最优路径function optimalExecuteTData({ indexMap, values: [values0], }: ExecutionDetails[ReadonlyArrayTData]): GrafastResultsListTData { return indexMap((i) values0.at(i)?.[0]); }批处理场景下Grafast 一次为多个“行”求值例如 GraphQL 连接中的每个父节点各取一次首项。optimalExecute借助indexMap对每个索引执行values0.at(i)?.[0]把“对数组取值并取首元素”合并为一次原子操作避免逐项装箱与重复分发。3.3 通用迭代器路径当isArray false时走类上的通用executeexecute({ indexMap, values: [values0] }): GrafastResultsListTData { return indexMap((i) { const val values0.at(i); if (val null) return val; if (Array.isArray(val)) return val[0]; // Iterable? Return the first entry return (async () { for await (const e of val) { return e; } return undefined; })(); }); }注意该实现依然是双保险即便传了false如果实际值是数组仍走val[0]只有遇到真迭代器时才用for await...of拉取首项迭代器为空时返回undefined。这也解释了文档为何要求迭代器场景显式传false——提前声明可让整个步骤保持同步安全而迭代器必须异步消费只能退化为异步结果。四、计划优化first(list([$a, $b]))直接化简为$aFirstStep重写了optimize()first.tsoptimize() { const parent this.getDep(0); // The first of a list plan is just the first dependency of the list plan. if (parent instanceof ListStep) { return parent.first(); } return this; }当被取首项的父步骤本身就是ListStep即“若干步骤的有序列表”步骤见 grafast/grafast/src/steps/list.ts 的first()方法时first(list([$a, $b, ...]))会在优化阶段被直接替换为其第一个依赖$a从而把“构造列表再取首项”这条链完全消除。这一点在官方文档 step-classes.mdx 中被作为“计划化简simplification”的典型用例专门讲解Similarlyfirst(list([$a, $b]))can be simplified to just$a.此外FirstStep还实现了[$$deepDepSkip]()first.ts告诉依赖分析器它的“深层依赖”就是那个列表步骤本身配合allowMultipleOptimizations true与恒等的deduplicate(peers)first.ts使得多个等价first调用可以在计划层安全合并、重复优化而不会破坏执行顺序。五、仓库内的真实落地用法first不是孤立的教学示例它在 dataplan-pg 与连接处理中被广泛使用PgSelectSingleStep取单行在 grafast/dataplan-pg/src/steps/pgSelect.ts 中return new PgSelectSingleStep(this, first(this, true), options);显式传true因为PgSelect的查询结果必然是数组可安全启用数组优化。该用法同样出现在官方教程 step-library/dataplan-pg/pgSelect.md 与 step-library/dataplan-pg/pgSelect.mdconst $firstUser $users.row(first($users));。PgUnionAllSingleStep在 grafast/dataplan-pg/src/steps/pgUnionAll.ts 中直接使用默认形态first(this)。连接步骤的_items()路径在 connection.ts 中ConnectionStep需要从游标优化后的集合中取首元素时也会调用first($connection._items(), isArray)并依据场景动态决定是否走数组优化。导出位置first作为标准步骤从 grafast/grafast/src/index.ts 等处多次导出配合FirstStep的$$exportmoduleName: grafast可被graphile-export等工具序列化复用。此外standard-steps/list.md 也把.first()列为ListStep的内置方法之一与独立的first步骤互为补充。六、实践要点小结默认用于数组列表步骤产出的值是普通数组或null/undefined时直接first($list)享受同步安全与values0.at(i)?.[0]快路径。迭代器必须显式声明传入异步迭代器时务必写first($iterable, false)否则会在运行时退化为异步路径并失去isSyncAndSafe保证。空列表语义无论哪条路径空数组/空迭代器都返回undefined不会抛错可安全用于可空字段。交给优化器化简不要手写first(list([...]))再担心开销——优化阶段会直接折叠为第一个依赖步骤。结合row()使用在 dataplan-pg 中$pgSelect.row(first($pgSelect))是“取查询结果首行”的标准姿势参数true表明结果必为数组。深入阅读建议first.ts 完整实现、StepRepresentingList 类型定义、ListStep.first()以及官方标准步骤目录 standard-steps。【免费下载链接】crystal Graphiles Crystal Monorepo; home to Grafast, PostGraphile, pg-introspection, pg-sql2 and much more!项目地址: https://gitcode.com/gh_mirrors/cry/crystal创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
企业数字化 ERP 产品动态
相关推荐
魔镜插件性能调优实战:3步解决卡顿,附完整示例 魔镜插件性能调优实战:3步解决卡顿,附完整示例 面试被问原理答不上来?很多后端开发在复盘时都栽在这一步。明明代码跑通了,性能却拉胯,魔镜插件的底层机制没吃透,优化全靠猜。今天不讲虚的,直接上 完整示例… · 2026/9/23 4:39:16
OpenZFS SysV init 脚本全解析:跨发行版可移植设计、启动顺序与安装配置指南 OpenZFS SysV init 脚本全解析:跨发行版可移植设计、启动顺序与安装配置指南 【免费下载链接】zfs OpenZFS on Linux and FreeBSD 项目地址: https://gitcode.com/gh_mirrors/zf/zfs
本文是 OpenZFS 传统 SysV init 脚本体系的实战指南,以 etc/in… · 2026/9/23 4:39:16
5种方案搞定诺基亚5320软件免费下载完整示例避坑指南 5种方案搞定诺基亚5320软件免费下载完整示例避坑指南 你是不是也遇到过这种情况:搜遍全网找诺基亚5320的SIS安装包,下载下来一堆杂七杂八的文件,装上去要么闪退,要么根本打不开?别急着骂娘,我干这行十年,见过太多人卡在“下载”这一步,却… · 2026/9/23 4:39:04
Python大熊猫互动拍照系统:姿态估计与图像融合技术实战解析 简介:这是一套面向毕业设计及AI图像处理学习的Python大熊猫主题互动拍照系统源码。项目围绕人工智能视觉技术,实现了动作识别、人像动漫化、风格迁移、熊猫贴纸合成、视频融合及定时拍照等完整功能,适合需要完成课程设计、毕业设计或希望实战… · 2026/9/23 23:22:35
疫情舆情情感分析实战:从pandas解析到朴素贝叶斯建模 简介:这是一份面向自然语言处理与舆情分析方向学习者、研究者的疫情情感分析完整项目,围绕2020年疫情期间人民日报与微博等平台话题数据,实现情感极性的两分类分析。资源整合了毕业论文文档、Python项目源码与多格式实验数据,共20… · 2026/9/23 23:22:28
气象站数据异常检测:基于Python的野值识别与参数调优 简介:基于Python的气象站异常检测系统源码包,面向数字信号处理课程学习者与气象数据分析爱好者,以气象站日平均气温数据为对象,通过空间图模型和时间序列分析自动识别异常站点。系统利用纬度差构建空间关系,结合历史气… · 2026/9/23 23:22:22
深度可分离UNet:医学图像分割轻量化设计与PyTorch实战 简介:深度可分离UNet是一套面向医学图像分割的轻量级模型及工程代码,适合算法工程师和研究人员在CPU/GPU环境快速实验。资源共10个文件,包括4个Python脚本、3个pyc缓存文件、1个README.md、1个requirements.txt和1个项目说明书docx࿰… · 2026/9/23 23:22:22
PRQL 的 Elixir 绑定:使用 Rustler NIF 在 Elixir 中编译 PRQL 查询 后端 【免费下载链接】prql PRQL is a modern language for transforming data — a simple, powerful, pipelined SQL replacement 项目地址: https://gitcode.com/gh_mirrors/pr/prql 点击查看 免费下载 本指南围绕 PRQL 仓库中的 Elixir 语言绑定(位… · 2026/9/23 23:22:22
3招搞定手机怎么下载微信面试难题实战项目解析 3招搞定手机怎么下载微信面试难题实战项目解析 面试被问“手机怎么下载微信”背后的原理,90%的人答不上来。别笑,这看似弱智的问题,实则是考察你对移动应用分发机制、安全校验及网络协议理解的试金石。我带过不少校招新人,他们背了八股文,却连一个A… · 2026/9/23 0:00:03
你有新短消息请注意查收:3个新手避坑指南搞定消息系统选型 你有新短消息请注意查收:3个新手避坑指南搞定消息系统选型 面试被问“高并发下如何保证消息不丢失”,你张口就是“用Redis”,结果面试官追问“如果Redis宕机了怎么办”,你瞬间卡壳。这种场景太常见了,很多新手在背八股文时,只记住了技术名词… · 2026/9/23 0:00:29