当我们需要用 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 条评论
博主 xuwu
芜湖
博主 悠
顶顶
博主 悠
@悠 ~~~~
博主 执念
hello,为啥不更新了
博主 妄想症拾柒
半年没更新了,期待博主新文章,一直都会支持~~~
博主 KEVI_
哇,好漂亮的博客,期待更新!
博主 yfcc
博主 。
厉害了
博主 自由如风
秀啊
博主 4-745D-47A2-A9B3-4367DA81B3F1
@自由如风 弟弟
博主 不吃梓梓
emmmmm,首先博主你的ICP备案号链接地址不对,小心查你。我最近已经收到消息要20号之前改好。
其次你的代码展示用的什么插件啊啊啊啊啊啊啊啊啊。
博主 幼稚.
有没有带哥教我Hosts
博主 lp
支持
博主 千羽
大佬咕咕咕一年惹!
博主 yc
支持,非常喜欢