Gatsby graphql with regex as variable - graphql

I would like to use regex with graphql query variable.
This does't return results:
export const query = graphql`
query(
$episodes: String!
) {
episodes: allMarkdownRemark(
filter: { fields: { slug: { regex: $episodes } } }
) {
edges {
node {
id
}
}
}
}
`;
However, this would work:
export const query = graphql`
query() {
episodes: allMarkdownRemark(
filter: { fields: { slug: { regex: "/episodes/travel/" } } }
) {
edges {
node {
id
}
}
}
}
`;
what's wrong?

Passing regex via query arguments should work, see the screenshot below. Make sure you're passing in the regex as string, not the actual regex. Also, you'll need to escape the middle slash:
context: {
- episodes: /episodes\/traveller/ <-- doesn't work
+ episodes: /episodes\/traveller/.toString() <-- works
or episodes: "/episodes\\/traveller/" <-- also works
}
Try it out in one of the graphiQL embed in this page

Related

Gatsby GraphQL query no longer working after update

So I had this graphql query on my gatsby site before they updated and now it no longer works.
query ($skip: Int!, $limit: Int!) {
allMdx(
filter: { fileAbsolutePath: { regex: "/posts/" } }
sort: { order: DESC, fields: frontmatter___date }
skip: $skip
limit: $limit
) {
nodes {
id
frontmatter {
alt
title
path
slug
date(formatString: "MMMM Do, YYYY")
image {
childImageSharp {
fluid {
...GatsbyImageSharpFluid
}
}
}
}
}
}
}
It says "fileAbsolutePath" is not defined by type mdxfilterinput
I don't know what other way to update this to make it show my data again because the other options don't make sense
What would I use in replace of fileabsolutepath for my graph ql query to work again with the new updated gatsby version?

Multiple queries in a component for Gatsby

I'm using Gatsby to createPages and then in the createPage method I'm referencing a specific component for the page
createPage({
path: node.path.alias,
component: path.resolve(`./src/layouts/custom-page/custom-page.js`),
context: {
articleId: node.id,
authorId: node.relationships.field_author.id
},
})
Within the layout (custom-page.js) I'm trying to do 2 queries but it's not working for me. When I test this query in GraphiQL it works fine.
export const query = graphql `
query ($articleId: String!, $authorId: String!) {
article: nodeArticle(id: {eq: $articleId}) {
title
body {
value
}
path {
alias
}
}
author: nodePerson(id: {eq: $authorId}) {
title
path {
alias
}
}
}
`;
Within my component I would then expect to be able to access the data with either data.author.title or data.article.title.
Is it possible to do this in Gatsby?
Your query is seemed to be bit wrong or some missing in the query.
Query should look like.
export const query = graphql `
query Articles($articleId: String!, $authorId: String!) {
article: nodeArticle(id: {eq: $articleId}) {
title
body {
value
}
path {
alias
}
}
author: nodePerson(id: {eq: $authorId}) {
title
path {
alias
}
}
}
`;
Better to use the package graphql-tag.
Your query will look like.
import gql from 'graphql-tag';
export const query = gql`
query Articles($articleId: String!, $authorId: String!) {
article: nodeArticle(id: {eq: $articleId}) {
title
body {
value
}
path {
alias
}
}
author: nodePerson(id: {eq: $authorId}) {
title
path {
alias
}
}
}
`;

Can I make my graphql query multipurpose?

I would like to query products by different filters and criteria so I have written multiple queries for my frontend for each case (shown below). Is there a way I can write and use one "multipurpose" query instead of these?
const GET_PRODUCTS = gql`
query {
products {
...productFragment
}
}
${PRODUCT_FRAGMENT}
`
const GET_PRODUCTS_BY_PRICE = gql`
query($sortFilter: String) {
products(sort: $sortFilter) {
# (sort: "price:asc") or (sort: "price:desc")
...productFragment
}
}
${PRODUCT_FRAGMENT}
`
const GET_PRODUCTS_BY_CATEGORY = gql`
query($categoryId: String) {
products(where: { categories: { id: $categoryId } }) {
...productFragment
}
}
${PRODUCT_FRAGMENT}
`
const GET_PRODUCTS_BY_CATEGORY_AND_PRICE = gql`
query($sortFilter: String, $categoryId: String) {
products(sort: $sortFilter, where: { categories: { id: $categoryId } }) {
...productFragment
}
}
${PRODUCT_FRAGMENT}
`
Looks like I can write a helper fn like this then:
function getRequiredProductsQuery({ sortFilter, categoryId }) {
if (sortFilter && categoryId) {
return { key: 'PRODUCTS_BY_CATEGORY_AND_PRICE', query: GET_PRODUCTS_BY_CATEGORY_AND_PRICE }
}
if (sortFilter) {
return { key: 'PRODUCTS_BY_PRICE', query: GET_PRODUCTS_BY_PRICE }
}
if (categoryId) {
return { key: 'PRODUCTS_BY_CATEGORY', query: GET_PRODUCTS_BY_CATEGORY }
}
return { key: 'PRODUCTS', query: GET_PRODUCTS }
}
Is it really all necessary?
ok, I figured that I can provide default params like $categoryId: String = "id:asc"

How to get field value having space, hyphen in REST API in GraphQL

REST API Endpoint - https://api.jikan.moe/v3/manga/13
"Alterantive version", "Side story" and "Spin-off" fields are having space and hyphen.
common_schema.js
const { gql } = require('apollo-server');
const typeDefs = gql`
type RelatedType {
Adaptation: [RelatedSubType]
SideStory: [RelatedSubType]
Character: [RelatedSubType]
Summary: [RelatedSubType]
Other: [RelatedSubType]
AlternativeVersion: [RelatedSubType]
SpinOff: [RelatedSubType]
}
type RelatedSubType {
mal_id: ID
type: String
name: String
url: String
}
`;
module.exports = typeDefs;
If I write field value as Spin-off or Alternative version then it gives an error in terminal. "Spin-off" also doesn't work. I know these aren't valid but then also tried.
manga_resolver.js
module.exports = {
Query: {
manga: (_, { id }, { dataSources }) =>
dataSources.mangaAPI.getMangaDetail(id)
}
};
manga.js
const { RESTDataSource } = require('apollo-datasource-rest');
class MangaAPI extends RESTDataSource {
constructor() {
super();
this.baseURL = 'https://api.jikan.moe/v3/manga/';
}
async getMangaDetail(mal_id) {
const response = await this.get(`/${mal_id}`);
return response;
}
}
module.exports = MangaAPI;
Query -
query getMangaDetail{
manga(id: 13){
related{
Adaptation{
name
}
AlternativeVersion{
name
}
SpinOff{
name
}
}
}
}
Getting null in those fields which are having space and hyphen.
Query result -
{
"data": {
"manga": {
"related": {
"Adaptation": [
{
"name": "One Piece"
}
],
"AlternativeVersion": null,
"SpinOff": null
}
}
}
}
Repository - jikan-graphql
According to the spec, names in GraphQL must follow this format:
/[_A-Za-z][_0-9A-Za-z]*/
In other words, neither spaces nor dashes are permitted. If your data source is returning property names that are formatted incorrectly, you can just provide resolvers for the fields in question:
const resolvers = {
RelatedType: {
sideStory: (parent) => {
return parent['Side story']
},
...
}
}

GraphQL filters in GatsbyJS

I'm having trouble understanding how to write filters for GraphQL queries in GatsbyJS.
This works:
filter: { contentType: { in: ["post", "page"] }
I basically need the reverse of that, like:
filter: { "post" in: { contentTypes } } // where contentTypes is array
That doesn't work because "NAME is expected" (where "post" is in my example).
After going through GatsbyJS docs I found this:
elemMatch: short for element match, this indicates that the field you are filtering will return an array of elements, on which you can apply a filter using the previous operators
filter:{
packageJson:{
dependencies:{
elemMatch:{
name:{
eq:"chokidar"
}
}
}
}
}
Great! That's what I need! So I try that, and I get:
error GraphQL Error Field "elemMatch" is not defined by type markdownRemarkConnectionFrontmatterTagsQueryList_2.
Keywords defined in markdownRemarkConnectionFrontmatterTagsQueryList_2 are:
eq: string | null;
ne: string | null;
regex: string | null;
glob: string | null;
in: Array | null;
Why am I limited to these keywords when more keywords such as elemMatch are mentioned in docs? Why am I not allowed to use the filter structure "element in: { array }"?
How can I create this filter?
Filter by value in an array
Let's say you have a markdown blog with categories as an array of string, you can filter posts with "historical" in categories like this:
{
allMarkdownRemark(filter:{
frontmatter:{
categories: {
in: ["historical"]
}
}
}) {
edges {
node {
id
frontmatter {
categories
}
}
}
}
}
You can try this query out in any of the graphiq blocks in Gatsby.js docs.
ElemMatch
I think elemMatch is only 'turned on' for fields with array of objects; something like comments: [{ id: "1", content: "" }, { id: "2", content: ""}]. This way, you can apply further filters on the fields of each comment:
comments: { elemMatch: { id: { eq: "1" } } }
Here's an example you can try out in the graphiq blocks in gatsby docs:
// only show plugins which have "#babel/runtime" as a dependency
{
allSitePlugin (filter:{
packageJson:{
dependencies: {
elemMatch: {
name: {
eq: "#babel/runtime"
}
}
}
}
}) {
edges {
node {
name
version
packageJson {
dependencies {
name
}
}
}
}
}
}

Resources