<p><span class="drop-cap">H</span>ere's a cheat sheet to show you a couple of examples of <strong>GraphQL</strong> queries using version <strong>8.x-3.x</strong> of <a href="https://www.drupal.org/project/graphql">Drupal's GraphQL module</a>. This list is not intended to be exhaustive, it's just a sample of common queries that I've used in almost all decoupled sites that I've worked on.</p>
<p>Enough talking, show me the code! ?</p>
<h2>Get a single node by its nid</h2>
<p>Suppose that we have a node with id <code>1</code>. To query the basic information about that node, we can use the query below.</p>
<pre>
<code class="language-json">query myQuery {
	nodeById(id: "1") {
		entityId
		title
		status
	}
}	</code></pre>
<p>Only fields that belong to all entities and nodes can be fetched using this query. Keep in mind that <strong>entityId</strong> belongs to all entities (a node is an entity), and <strong>title</strong> and <strong>status</strong> are fields of all nodes, regardless of their bundle.</p>
<h2>Get a single node of a specific content type by its nid</h2>
<p>If we want to retrieve fields that belong only to a specific content type we have to use the fragment associated with that content type. For example, suppose that we have the <strong>Article</strong> content type, and it has the <strong>field_kicker</strong> field, so in order to get the value of the <strong>field_kicker</strong>, wrap the <strong>fieldKicker</strong> field inside the <strong>NodeArticle</strong> fragment.</p>
<pre>
<code class="language-json">query myQuery {
	nodeById(id: "1") {
		entityId
		title
		status
		... on NodeArticle {
			fieldKicker
		}
	}
}</code></pre>
<p>Remember that fields and properties are in <em>camelCase</em>, so <strong>field_kicker</strong> becomes <strong>fieldKicker</strong>. On the other hand, the nodes' fragments name has the form <em>Node</em> + <em>Content Type name</em>, so the fragment for the content type <strong>Article</strong> is <strong>NodeArticle</strong>.</p>
<h2>Querying a list of nodes</h2>
<p>Imagine that our content type <strong>Article</strong> has the field <strong>field_section</strong> that indicates the section the article belongs to. For the sake of simplicity, suppose that sections are stored as strings. So, to get the 10 latest articles of <em>Sports</em> section, we can use the next query.</p>
<pre>
<code class="language-json">query myQuery {
		nodeQuery(
			filter: {
				conditions: [
					{ field: "type", value: "article" },
					{ field: "status", value: "1" },
					{ field: "field_section", value: "sports" },
				]
			},
			sort: { field: "created", direction: DESC },
			limit: 10,
		) {
			entities {
				entityId
				entityLabel
			}
		}
}</code></pre>
<p>If you want to filter by an entity reference, use the referenced entity id in the "<em>value</em>" field.</p>
<h2>Querying taxonomy terms</h2>
<p>To get a taxonomy terms list of a specific vocabulary, for example, the "<em>tags</em>" vocabulary, use a query like the one below.</p>
<pre>
<code class="language-json">query myQuery {
	taxonomyTermQuery(
		filter: {
			conditions: [
				{ field: "vid", value: "tags" },
				{ field: "status", value: "1" },
			],
		},
	) {
		entities {
			entityId
			entityLabel
		}
	}
}</code></pre>
<h2>Using aliases</h2>
<p>We can rename the result of a field to anything we want.</p>
<pre>
<code class="language-json">query myQuery {
		nodeById(id: "1") {
			id: entityId
			title
			... on NodeArticle {
				section: fieldSection
			}
		}
}</code></pre>
<p>And we'll get the result</p>
<pre>
<code class="language-json">{
  "data": {
    "nodeById": {
      "id": "1",
      "title": "My awesome article!",
      "section": "sports"
    }
  }
}</code></pre>
<p>Sometimes is necessary to use aliases, for example when we want to make the same query in a single request.</p>
<pre>
<code class="language-json">query myQuery {
	tags: taxonomyTermQuery(
		filter: { conditions: [{ field: "vid", value: "tags" }] },
	) {
		entities {
			entityLabel
		}
	}
	topics: taxonomyTermQuery(
		filter: { conditions: [{ field: "vid", value: "topics" }] },
	) {
		entities {
			entityLabel
		}
	}
}</code></pre>
<p>In the example above we are querying <em>tags</em> and <em>topics</em> using <strong>taxonomyTermQuery</strong> in both cases, so in order to differentiate the results, we are forced to use aliases.</p>
<h2>Using fragments</h2>
<p>There are times when we want to reuse the same query in many places. For example, suppose that our articles have a field <strong>field_tags</strong> that reference taxonomy terms of vocabulary <strong>Tags</strong>, and in another part of our site we show a list of those tags in the same way that we do in the articles, I mean, using the same fields. In these kinds of cases, fragments are useful to avoid code duplication.</p>
<pre>
<code class="language-json">query myQuery {
	article: nodeById(id: "1") {
		id: entityId
		title
		... on NodeArticle {
			fieldTags {
				entity {
					...Tag
				}
			}
		}
	}
	tags: taxonomyTermQuery(
		filter: { conditions: [{ field: "vid", value: "tags" }] },
	) {
		entities {
			...Tag
		}
	}
}
fragment Tag on TaxonomyTermTags {
	id: entityId
	name: entityLabel
}</code></pre>
<h2>Querying referenced paragraphs</h2>
<p>A very common use case for paragraphs is when a content type has a field that can reference multiple types of paragraphs. For example, the content type <strong>Page</strong> can have a <strong>field_sections</strong> field that references paragraphs of type <strong>tag_section</strong> for showing the latest tags, and a paragraph of type <strong>articles_section</strong> for the latest articles. We are not limited to show only one type of paragraph per field, to query all the values for the <strong>field_section</strong> we just need to list the supported fragments for that field. It'll be clear with an example.</p>
<pre>
<code class="language-json">query myQuery {
	page: nodeById(id: "2") {
		title
		... on NodePage {
			fieldSections {
				entity {
					...TagSection
					...ArticlesSection
				}
			}
		}
	}
}
fragment TagSection on ParagraphTagSection {
	# The required fields
}
fragment ArticlesSection on ParagraphTagSection {
	# The required fields
}</code></pre>
<p>The use of fragments in the query above is not necessary but makes the code more readable. Note that even though the first listed fragment is the <strong>TagSection</strong>, this doesn't mean that the section to appear first will be the <strong>TagSection</strong>, the order saved in the CMS is preserved.</p>
<h2>Querying image with Image Styles</h2>
<p>Suppose that we have an image style <strong>square_max_800_px</strong> as machine name, in <strong>GraphQL</strong> the image style name is transformed to <strong>SQUAREMAX800PX</strong>. Note how the underscores are dropped and the image style's machine name is capitalized.</p>
<pre>
<code class="language-json">query myQuery {
	nodeById(id: "1") {
		title
		fieldImage {
			url
			alt
			title
			squareStyle: derivative(style: SQUAREMAX800PX) {
				url
				width
				height
			}
		}
	}
}</code></pre>
<p>We can fetch more than one image style per single query using aliases.</p>
<pre>
<code class="language-json">query myQuery {
	nodeById(id: "1") {
		title
		fieldImage {
			url
			alt
			title
			squareStyle: derivative(style: SQUAREMAX800PX) {
				url
				width
				height
			}
			wideStyle: derivative(style: WIDEMAX800PX) {
				url
				width
				height
			}
		}
	}
}</code></pre>
<h2>Format dates</h2>
<p><strong>GraphQL</strong> supports some data transformations out of the box, for example, to format dates.</p>
<pre>
<code class="language-json">query myQuery {
	nodeById(id: "1") {
		title
		created: entityCreated(format: "d/m/yy")
	}
}</code></pre>
<p>The <a href="https://www.php.net/manual/es/function.date">available formats</a> are those supported by the date function in PHP.</p>
<p> </p>