Newsletter
TechAnV Blog
Get updates on security engineering, Rust, eBPF, and DevSecOps. No spam, unsubscribe anytime.
Check your inbox and click the confirmation link to complete your subscription.
GraphQL fragments#
One of the scripts that builds and deploys datasette.io uses a GraphQL query to retrieve information from GitHub about the repositories used for the various Datasette tools and plugins.
That query was very big - over 4,000 lines long!
That’s because it was shaped like this:
1{2 repo_0: repository(name: "datasette-query-history", owner: "bretwalker") {3 id4 nameWithOwner5 createdAt6 openGraphImageUrl7 usesCustomOpenGraphImage8 defaultBranchRef {9 target {10 oid11 }12 }13 repositoryTopics(first: 100) {14 totalCount15 nodes {16 topic {17 name18 }19 }20 }21 openIssueCount: issues(states: [OPEN]) {22 totalCount23 }24 closedIssueCount: issues(states: [CLOSED]) {25 totalCount26 }27 releases(last: 1) {28 totalCount29 nodes {30 tagName31 }32 }33 }34 # ...35 repo_137: repository(name: "yaml-to-sqlite", owner: "simonw") {36 id37 nameWithOwner38 createdAt39 openGraphImageUrl40 usesCustomOpenGraphImage41 defaultBranchRef {42 target {43 oid44 }45 }46 repositoryTopics(first: 100) {47 totalCount48 nodes {49 topic {50 name51 }52 }53 }54 openIssueCount: issues(states: [OPEN]) {55 totalCount56 }57 closedIssueCount: issues(states: [CLOSED]) {58 totalCount59 }60 releases(last: 1) {61 totalCount62 nodes {63 tagName64 }65 }66 }67}That block was repeated for every repository - 138 in total!
I figured there was likely a way to do this more efficiently, and it turns out there is: GraphQL fragments.
Here’s that example query rewritten to use fragments instead:
1fragment repoFields on Repository {2 id3 nameWithOwner4 createdAt5 openGraphImageUrl6 usesCustomOpenGraphImage7 defaultBranchRef {8 target {9 oid10 }11 }12 repositoryTopics(first: 100) {13 totalCount14 nodes {15 topic {16 name17 }18 }19 }20 openIssueCount: issues(states: [OPEN]) {21 totalCount22 }23 closedIssueCount: issues(states: [CLOSED]) {24 totalCount25 }26 releases(last: 1) {27 totalCount28 nodes {29 tagName30 }31 }32}33{34 repo_0: repository(name: "datasette-query-history", owner: "bretwalker") {35 ...repoFields36 }37 repo_137: repository(name: "yaml-to-sqlite", owner: "simonw") {38 ...repoFields39 }40}Now each additional repo added to the query is only 3 extra lines of GraphQL, not 30!