GraphQL中如何实现Where条件的subscriptionName按需生效?
我有如下GraphQL查询:
query GET_APM_BY_RG($subscriptionName: [String!], $resourceGroupName: [String!], $userAzureId: String!) { dashboardFilters( findoptions: { distinct: ["apm"] select: { apm: true } where: { subscription: { subscriptionName : { in: $subscriptionName} resourceGroupName: { in: $resourceGroupName } } requestors: { some: { requestorId: $userAzureId } } } } ) }
需求是:where条件中的subscriptionName仅在传入$subscriptionName参数时生效,否则不应用该条件。
尝试的方法及错误
1. 使用@include指令
尝试给subscriptionName的过滤条件加上@include指令,代码如下:
query GET_APM_BY_RG($subscriptionName: [String!], $resourceGroupName: [String!], $userAzureId: String!) { dashboardFilters( findoptions: { distinct: ["apm"] select: { apm: true } where: { subscription: { subscriptionName : { in: $subscriptionName} @include(if: $subscriptionName) resourceGroupName: { in: $resourceGroupName } } requestors: { some: { requestorId: $userAzureId } } } } ) }
但触发语法错误:
Uncaught GraphQLError: Syntax Error:
Expected Name, found "@".
原因是GraphQL的指令仅能作用于字段名,不能直接用在输入对象的属性上。
2. 尝试传入整个where子句变量
把where子句做成变量传入,代码如下:
query GET_APM_BY_RG( $subscriptionName: [String!] $resourceGroupName: [String!] $userAzureId: String! $whereClause: QueryEventInput! ) { dashboardFilters( findoptions: { distinct: ["apm"] select: { apm: true } where: $whereClause } ) }
但报错:
Unknown type "QueryEventInput".
可行的解决方案
方案1:依赖后端对null参数的处理
将$subscriptionName保持为可选参数(当前类型[String!]默认支持nullable),查询中保留subscriptionName: { in: $subscriptionName }即可。大部分GraphQL后端框架(比如Prisma、TypeGraphQL)会自动忽略值为null的过滤条件;如果后端无默认处理,需在服务端逻辑中判断:当$subscriptionName为null或空数组时,跳过该字段的过滤。
方案2:客户端动态构建where输入对象
在发起请求前,根据$subscriptionName是否存在,动态组装where内的subscription对象:
- 若
$subscriptionName有值,subscription对象同时包含subscriptionName和resourceGroupName过滤 - 若
$subscriptionName为空或未传入,subscription对象仅保留resourceGroupName过滤
示例(JavaScript代码):
const buildWhereClause = (subscriptionName, resourceGroupName, userAzureId) => { const subscriptionFilter = { resourceGroupName: { in: resourceGroupName } }; if (subscriptionName && subscriptionName.length > 0) { subscriptionFilter.subscriptionName = { in: subscriptionName }; } return { subscription: subscriptionFilter, requestors: { some: { requestorId: userAzureId } } }; }; // 发起请求时使用构建好的条件 const whereClause = buildWhereClause(subscriptionNameParam, resourceGroupNameParam, userAzureIdParam);
方案3:定义合法的输入类型(解决QueryEventInput错误)
如果要使用整个where子句作为变量传入,需先在GraphQL Schema中定义匹配where参数类型的QueryEventInput:
input SubscriptionFilterInput { subscriptionName: [String!] resourceGroupName: [String!] } input RequestorFilterInput { some: { requestorId: String! } } input QueryEventInput { subscription: SubscriptionFilterInput requestors: RequestorFilterInput }
定义完成后,即可在查询中使用$whereClause: QueryEventInput变量,再由客户端根据参数是否存在动态构建变量值。
内容的提问来源于stack exchange,提问作者Khushboo Sharma

