enonic-guillotine-query-builder
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseEnonic Guillotine Query Builder
Enonic Guillotine 查询构建器
Procedures
操作流程
Step 1: Scan the workspace for existing Guillotine usage
- Execute to inventory files containing Guillotine markers (query strings, library imports, endpoint references).
node scripts/find-guillotine-targets.mjs . - If a Node runtime is unavailable, search the workspace manually for ,
guillotine,queryDsl, orqueryDslConnectionin/lib/guillotine,.ts,.js, and.graphqlfiles..gql - Note the Guillotine version in use: if string-based fields are found, the project uses the deprecated 5.x-style API; if
query(query: "...")/queryDslare found, the project uses 6.x+ DSL.queryDslConnection - If both styles coexist, flag the deprecated usage for migration.
Step 2: Load the Guillotine API reference
- Read before composing any query.
references/guillotine-reference.md - Read when the workspace targets or migrates between Guillotine versions.
references/compatibility.md
Step 3: Determine the query shape
- Identify the operation the user needs:
- Single content fetch: Use .
get(key) - Direct children: Use or
getChildren(key)for pagination.getChildrenConnection(key) - Filtered search: Use for a flat list or
queryDsl(query)for pagination, aggregations, or highlighting.queryDslConnection(query) - Content type metadata: Use or
getType(name).getTypes
- Single content fetch: Use
- If pagination is needed, prefer connection variants (,
queryDslConnection) and guide the caller to passgetChildrenConnection/after.first - If aggregations or highlighting are needed, require — these features are not available on
queryDslConnection.queryDsl
Step 4: Construct the content type fragment
- Derive the GraphQL type name from the content type descriptor by replacing dots () and colons (
.) with underscores (:), and removing hyphens (_) while capitalizing the following letter. The first letter of each segment after a colon is capitalized. Example:-→com.enonic.app.myapp:BlogPost. For built-in types:com_enonic_app_myapp_BlogPost→portal:template-folder.portal_TemplateFolder - Use an inline fragment to access the type-specific field:
data.... on <GraphQLTypeName> { data { ... } } - For content references (ContentSelector, ImageSelector, MediaSelector), follow the reference with a nested inline fragment on the target type.
- For RichText / HtmlArea fields, include and optionally
processedHtml,links,imagessub-fields. Use themacrosinput argument for absolute URLs or srcset widths.processHtml
Step 5: Build query filters and sorting
- Use Query DSL input types. Each must contain exactly one expression field.
QueryDSLInput - Combine multiple conditions using with
boolean,must,should, andmustNotarrays.filter - For date or numeric ranges, use the expression with
range/gt/gte/ltand the correctltetype (DSLExpressionValueInput,localDate,localDateTime,instant,long).double - For sorting, use with
SortDslInputandfield(direction/ASC).DESC - Read when the query pattern matches a documented example.
references/examples.md
Step 6: Add aggregations and highlighting (if needed)
- Pass as an array of
aggregationsobjects onAggregationInput.queryDslConnection - Each aggregation requires a unique and exactly one aggregation type field (
name,terms,dateRange, etc.).stats - For highlighting, pass with a
highlightarray specifyingpropertiesfor each field to highlight.propertyName - Read aggregation and highlight results from and
aggregationsAsJsonon the connection result.highlightAsJson
Step 7: Generate TypeScript types (if requested)
- Read as the starting template.
assets/guillotine-query.template.ts - Replace ,
__APP_KEY__,__CONTENT_TYPE__, and__GRAPHQL_TYPE__placeholders with the actual content type values.__FIELDS__ - Add typed fields to the interface matching the content type schema fields requested in the query.
Data - For connection queries, use the generic with the specific content type.
ContentConnection<T>
Step 8: Set site context (if applicable)
- If the query targets a specific site, set on the
siteKeyfield or instruct the caller to set theguillotineHTTP header.X-Guillotine-SiteKey - Use placeholder in path arguments for site-relative queries.
${site} - Use to return site-relative paths.
_path(type: siteRelative)
Step 9: Validate the query
- Verify all inline fragment type names use underscores, not the original descriptor format.
- Confirm /
queryDslare used instead of the deprecatedqueryDslConnection/query.queryConnection - Ensure objects contain exactly one expression field.
QueryDSLInput - Verify objects contain exactly one value type field.
DSLExpressionValueInput - Check that aggregation and highlight are only used on connection variants.
- Read if the query returns unexpected nulls, empty results, or type errors.
references/troubleshooting.md
步骤1:扫描工作区中现有的Guillotine使用情况
- 执行来盘点包含Guillotine标记(查询字符串、库导入、端点引用)的文件。
node scripts/find-guillotine-targets.mjs . - 如果没有Node运行时,手动在工作区的、
.ts、.js和.graphql文件中搜索.gql、guillotine、queryDsl或queryDslConnection。/lib/guillotine - 记录使用的Guillotine版本:如果发现了基于字符串的字段,说明项目使用的是已弃用的5.x风格API;如果发现
query(query: "...")/queryDsl,则项目使用6.x+的DSL。queryDslConnection - 如果两种风格共存,标记弃用用法以便迁移。
步骤2:加载Guillotine API参考
- 编写任何查询之前先阅读。
references/guillotine-reference.md - 当工作区要适配Guillotine版本或在不同版本间迁移时,阅读。
references/compatibility.md
步骤3:确定查询结构
- 识别用户需要的操作:
- 单内容获取:使用。
get(key) - 直接子内容:使用,需要分页时使用
getChildren(key)。getChildrenConnection(key) - 带过滤的搜索:获取平级列表使用,需要分页、聚合或高亮时使用
queryDsl(query)。queryDslConnection(query) - 内容类型元数据:使用或
getType(name)。getTypes
- 单内容获取:使用
- 如果需要分页,优先使用连接变体(、
queryDslConnection),引导调用方传入getChildrenConnection/after参数。first - 如果需要聚合或高亮功能,必须使用——
queryDslConnection不支持这些特性。queryDsl
步骤4:构建内容类型片段
- 从内容类型描述符推导GraphQL类型名:将点()和冒号(
.)替换为下划线(:),删除连字符(_并将后续字母大写,冒号后每个分段的首字母大写。示例:-→com.enonic.app.myapp:BlogPost。内置类型示例:com_enonic_app_myapp_BlogPost→portal:template-folder。portal_TemplateFolder - 使用内联片段访问类型专属的字段:
data。... on <GraphQLTypeName> { data { ... } } - 对于内容引用(ContentSelector、ImageSelector、MediaSelector),在引用后添加针对目标类型的嵌套内联片段。
- 对于RichText / HtmlArea字段,包含,可选包含
processedHtml、links、images子字段。需要绝对URL或srcset宽度时使用macros输入参数。processHtml
步骤5:构建查询过滤和排序规则
- 使用Query DSL输入类型,每个必须仅包含一个表达式字段。
QueryDSLInput - 使用搭配
boolean、must、should和mustNot数组组合多个条件。filter - 对于日期或数值范围,使用表达式搭配
range/gt/gte/lt和正确的lte类型(DSLExpressionValueInput、localDate、localDateTime、instant、long)。double - 排序时使用搭配
SortDslInput和field(direction/ASC)。DESC - 如果查询模式与文档中的示例匹配,可参考。
references/examples.md
步骤6:添加聚合和高亮(如有需要)
- 在上将
queryDslConnection作为aggregations对象数组传入。AggregationInput - 每个聚合需要唯一的和仅一个聚合类型字段(
name、terms、dateRange等)。stats - 高亮功能需传入,其
highlight数组指定每个要高亮的字段的properties。propertyName - 从连接结果的和
aggregationsAsJson中读取聚合和高亮结果。highlightAsJson
步骤7:生成TypeScript类型(如有需求)
- 读取作为初始模板。
assets/guillotine-query.template.ts - 将、
__APP_KEY__、__CONTENT_TYPE__和__GRAPHQL_TYPE__占位符替换为实际的内容类型值。__FIELDS__ - 在接口中添加与查询中请求的内容类型schema字段匹配的带类型字段。
Data - 对于连接查询,使用搭配具体内容类型的泛型。
ContentConnection<T>
步骤8:设置站点上下文(如适用)
- 如果查询针对特定站点,在字段上设置
guillotine,或指导调用方设置siteKeyHTTP头。X-Guillotine-SiteKey - 在路径参数中使用占位符实现站点相对查询。
${site} - 使用返回站点相对路径。
_path(type: siteRelative)
步骤9:验证查询
- 确认所有内联片段类型名使用下划线,而非原始描述符格式。
- 确认使用的是/
queryDsl而非已弃用的queryDslConnection/query。queryConnection - 确保对象仅包含一个表达式字段。
QueryDSLInput - 确认对象仅包含一个值类型字段。
DSLExpressionValueInput - 检查聚合和高亮仅在连接变体上使用。
- 如果查询返回意外的null、空结果或类型错误,参考。
references/troubleshooting.md
Error Handling
错误处理
- If returns null, verify the key is a valid content path or ID and that the correct branch (draft vs master) is targeted.
get - If inline fragment fields are null, confirm the GraphQL type name uses underscores and matches the content type descriptor exactly.
- If returns empty results, simplify to
queryDslto confirm data exists, then re-add filters one at a time.matchAll: {} - If aggregation or highlight results are null, verify the query uses , not
queryDslConnection.queryDsl - If the deprecated field is used, read
queryto migrate toreferences/compatibility.mdwith DSL syntax.queryDsl - If cannot run, scan the workspace manually for Guillotine markers and continue.
scripts/find-guillotine-targets.mjs
- 如果返回null,验证key是有效的内容路径或ID,且目标分支正确(草稿版 vs 正式版)。
get - 如果内联片段字段为null,确认GraphQL类型名使用下划线,且与内容类型描述符完全匹配。
- 如果返回空结果,简化为
queryDsl确认数据存在,再逐个重新添加过滤条件。matchAll: {} - 如果聚合或高亮结果为null,确认查询使用的是而非
queryDslConnection。queryDsl - 如果使用了已弃用的字段,参考
query迁移到使用DSL语法的references/compatibility.md。queryDsl - 如果无法运行,手动扫描工作区的Guillotine标记后继续操作。
scripts/find-guillotine-targets.mjs