GraphQL带where子句动态查询 如何处理可选过滤参数
问题原因
你当前的写法存在两个核心问题:
- 传
""跳过过滤的逻辑是错误的:你在where条件中固定写了三个_eq等值匹配规则,当传入空字符串时,数据库会执行slug = ""的匹配逻辑,你的库中没有对应slug为空的记录,自然返回空结果。 - 现有的查询没有做可选过滤的兼容,所有条件都是强制生效的,不管参数值是什么都会参与查询判断。
解决方案
这里提供三种适配可选过滤的实现方式,你可以根据自己的使用场景选择:
方案1:Hasura原生条件逻辑(依赖Hasura GraphQL引擎)
你使用的查询语法是Hasura的标准语法,可以直接在where中增加参数非空判断逻辑,实现参数为null时自动跳过过滤:
query getJobsSearch($location: String = null, $type: String = null, $category: String = null) { jobs( order_by: {created_at: desc}, where: { deleted_at: {_is_null: true}, created_at: {_gt: "2021-06-16T10:06:38.551984+00:00"}, _and: [ { _or: [ { $location: { _is_null: true } }, { location: { slug: { _eq: $location } } } ] }, { _or: [ { $category: { _is_null: true } }, { job_category: { slug: { _eq: $category } } } ] }, { _or: [ { $type: { _is_null: true } }, { job_type: { slug: { _eq: $type } } } ] } ] }, limit: 50 ) { jobId title company_name job_category { name slug } job_type { name slug } isRemote location { city slug } created_at } }
传参规则:
- 查全量数据:直接传
{"location": null, "type": null, "category": null}或者空对象{}即可 - 单条件过滤:比如只按location查询,传
{"location": "new-delhi"},另外两个参数不传默认是null,自动跳过对应过滤
方案2:通用GraphQL @skip指令(不依赖后端实现)
用GraphQL原生的@skip指令控制是否加载对应过滤条件,兼容性更强:
query getJobsSearch( $location: String = null, $type: String = null, $category: String = null, $skipLocation: Boolean! = true, $skipCategory: Boolean! = true, $skipType: Boolean! = true ) { jobs( order_by: {created_at: desc}, where: { deleted_at: {_is_null: true}, created_at: {_gt: "2021-06-16T10:06:38.551984+00:00"}, location: {slug: {_eq: $location}} @skip(if: $skipLocation), job_category: {slug: {_eq: $category}} @skip(if: $skipCategory), job_type: {slug: {_eq: $type}} @skip(if: $skipType) }, limit: 50 ) { # 原有返回字段不变 } }
传参规则:
- 查全量数据:不需要传任何参数,三个skip默认都是true,自动跳过所有过滤
- 单条件过滤:比如只按location查询,传
{"location": "new-delhi", "skipLocation": false}即可
方案3:业务代码动态拼接条件(最接近Ruby链式查询的写法)
你可以在业务代码中像Ruby链式查询一样,有值的时候才拼接对应过滤条件,最后把整个where作为变量传给GraphQL:
// 示例:JS代码中的逻辑 const baseWhere = { deleted_at: {_is_null: true}, created_at: {_gt: "2021-06-16T10:06:38.551984+00:00"} } // 有值才追加条件,和Ruby链式查询逻辑一致 if (location) baseWhere.location = {slug: {_eq: location}} if (category) baseWhere.job_category = {slug: {_eq: category}} if (type) baseWhere.job_type = {slug: {_eq: type}} // 执行查询时把baseWhere作为where变量传入即可
对应的查询语句可以简化为:
query getJobsSearch($where: jobs_bool_exp!) { jobs( order_by: {created_at: desc}, where: $where, limit: 50 ) { # 原有返回字段不变 } }
内容的提问来源于stack exchange,提问作者Harsha M V
相关产品推荐
相关产品推荐

