当我们需要用 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 条评论
博主 橙子
lut好厉害hiahiahia
真的超棒诶
博主 双喜
@橙子 新乡的小伙伴你好👋
博主 橙子
(°∀°)ノ
博主 橙子
博主 空白zz
这个网站太好了
博主 健身资讯
赞!我来打卡了!谢谢分享
博主 Keep silent
网站很好看
博主 陳羽蒙
NB
博主 菜鸟
博主太厉害了 来膜拜一下
博主 凡
好漂亮的网站
博主 aqgfe
空包代发、一件代发快递就发www.danhw.com
博主 debu
酷啊
博主 13686760773
谢谢博主学到了很多
博主 Dynamic_Pigeon
好棒
博主 Envy
很漂亮的博客欸
博主 Cboy
看看
博主 幼稚.
这个网站是干啥的觉得好有趣啊www