当我们需要用 GraphQL 查询多层套嵌的数据,比如像 WordPress 这样套嵌的评论信息时,通常的写法是:
{
posts(first: 100) {
nodes {
id
title
comments {
nodes {
...CommentFields
replies: children {
nodes {
...CommentFields
replies: children {
nodes {
...CommentFields
replies: children {
nodes {
...CommentFields
replies: children {
nodes {
...CommentFields
}
}
}
}
}
}
}
}
}
}
}
}
}
fragment CommentFields on Comment {
id
date
type
approved
content
}
以上的写法只实现了四层套嵌评论的查询,很麻烦对不对?这或许是 GraphQL 的缺陷,但这也或许正体现了 GraphQL 的设计理念——所得即所查。
找了一下,没有现成的轮子,就自己写一个套嵌实现吧(注意 graphql 查询语句要顶头写,多余的缩进会影响递归结果):
import ApolloClient from 'apollo-boost'
import gql from 'graphql-tag'
class getPostCommentByPostId {
private postId: number
private MaxChildrenLevel: number
private data: any
/**
* @param {number} postId wordpress post id
* @param {number} MaxChildrenLevel post threaded (nested) comments levels deep (/wp-admin/options-discussion.php)
*/
public constructor(postId: number, MaxChildrenLevel) {
this.postId = postId
this.MaxChildrenLevel = MaxChildrenLevel
}
// 处理递归部分
private queryChildren() {
let queryHeader: string = ``
let queryFooter: string = ``
// 迭代之前的内容
const childrenHeader: string = `
children {
nodes {
...CommentFields`
// 迭代之后的内容
const childrenFooter: string = `
}
}`
// 处理每行前的空格
let addTabs = function (str: string, n: number) {
return str.replace(/^/gm, ' '.repeat(n)) // 注意我用的是两格缩进,四格缩进请自行调整
}
for (let i = 0; i < this.MaxChildrenLevel; i++) {
queryHeader = addTabs(childrenHeader + queryHeader, 2)
queryFooter = addTabs(queryFooter + childrenFooter, 2)
}
return addTabs(queryHeader + queryFooter, 2)
}
// 查询部分
private query() {
const client: ApolloClient = new ApolloClient()
client.query({
query: gql`
query GET_POST($postId: Int) {
postBy(postId: $postId) {
id
postId
title
date
uri
content
}
comments {
edges {
node {
...CommentFields${this.queryChildren()}
}
}
}
}
fragment CommentFields on Comment {
date
agent
content(format: RENDERED)
commentId
author {
... on CommentAuthor {
email
name
url
}
}
authorIp
}
`,
variables: {
"postId": this.postId
},
})
.then(data => console.log(data))
.catch(error => console.log(error))
}
}
「樱花庄的白猫」原创文章:《GraphQL 实现递归查询》,转载请保留出处!https://2heng.xin/2019/12/31/graphql-recursion/
Q.E.D.
Comments | 53 条评论
博主 jim
监控页面个挂了哦
博主 Mikewind
。
博主 Mikewind
还在吗
博主 Mikewind
@Mikewind 。
博主 Death 撒旦
支持
博主 如果有刀
请问
博主 CnZ1Jay
谢谢博主 学到了很多
博主 Nyan
博主 幼稚.
一堆技术宅~
博主 有憾
厉害了
博主 好你个如果
评论里反斜杠貌似会被吞掉
$$
S=\sum_{j=1}^Ns_j
$$
博主 A.S
。。。。。。
博主 一条酸菜鱼
那个,graphql和sql有啥区别啊
博主 Mashiro
@一条酸菜鱼 gql是用来做API查询的,sql是用来做数据库的,虽然都是查询语言但是语法和功能上差别都很大
博主 一条酸菜鱼
@Mashiro 明白了,谢谢博主
博主 iherb
收藏下
感谢分享
博主 于长野
看不懂,但还是要评论一下,表示来过
博主 Forex Trading
您好,我来自V2EX,希望能跟您交换友情链接。
我的博客也基本上是技术类文章,全部都是原创内容。
希望得到回复,我的博客地址是:https://www.fi-forex.com/
非常感谢!
博主 rtyu3221
@Forex Trading 前来学习
博主 蝉时雨
博客页脚日历?该更新了!
GraphQL 嵌套太多且不直观,主要还是字符串的查询语句很容易出错,用了 Github GraphQL Api 后发现并没有想象的好用
Σ( ̄□ ̄||)
博主 Mashiro
@蝉时雨 是的,而且写后端贼蛮烦,rest api随便设置两个参数查询一下就可以了,graphql非要connection什么的,,大概还是我太菜了吧