gatsby-source-strapi
gatsby-source-strapi copied to clipboard
Graphql filter on one type doesn't work
Hi,
Question: I use the queries below in the gatsby-graphql playground. When I use the current query:
query MyQuery {
allStrapiJob(filter: {data: {elemMatch: {id: {eq: 2}}}}) {
nodes {
data {
attributes {
slug
title
}
id
}
id
}
}
}
I get this as a result
{
"data": {
"allStrapiJob": {
"nodes": [
{
"data": [
{
"attributes": {
"slug": "helpdesk-engineer-uk",
"title": "Helpdesk Engineer"
},
"id": 1
},
{
"attributes": {
"slug": "frontend-developer",
"title": "Frontend developer"
},
"id": 2
}
],
"id": "Job_undefined"
}
]
}
},
"extensions": {}
}
Always 2 results (there are 2 entries in strapi at the moment) If I change the id to filter, to either 1 or 2, I always get 2 results. When changing it to anything else then 1 or 2, I get nothing as a result.
What am I doing wrong here?
Also, I got "strapiJob" to use.
query MyQuery {
strapiJob(data: {elemMatch: {id: {eq: 1}}}) {
data {
attributes {
slug
title
description
}
id
}
}
}
Same result, always 2 entries.
Seems that this is due to the fact that the nodes are wrapped in a data object. So the node that includes the slug is returned, which is in fact everything. But.... Correct me if I'm wrong.
@jan-wagenaar These queries are made in the graphql playground from gatsby. So that's how the queries need to be build...I guess? There is no other way to get those slug/title/description...
@jan-wagenaar These queries are made in the graphql playground from gatsby. So that's how the queries need to be build...I guess? There is no other way to get those slug/title/description...
I also encounter this problem and don't know how to solve it😭
@gzhanghui actually happy to see I'm not the only one :)
@jan-wagenaar These queries are made in the graphql playground from gatsby. So that's how the queries need to be build...I guess? There is no other way to get those slug/title/description...
Yeah I do not know an workaround either. RIght now I'm retrieving everything and use an array.filter() to get the right item. But definitely feels too hacky.
@jan-wagenaar if you are dealing with a large dataset, that is indeed not a solid solution... This needs to be addressed to the core-team, imo...
Is your query for a page?
In that case, one thing you should try if it's possible to use the Gatsby Node API to filter the data on build time. Then pass a custom object to your screen.
edit: see gatsby docs: https://www.gatsbyjs.com/docs/reference/config-files/gatsby-node/
It's for a page, off course, but gatsby node api needs the same query as far as I know...
That right, but in the gatsby-node.js code you may be able to implement custom logic.
I will try it for myself. Ofcourse, this is a temporary workaround....
That could work yes... create a clone of the nodes[0].data array and the custom logic would be to find the current node again in the cloned array, use that data to pas it to the template an remove that from the cloned array again; so that on the next cycle of the foreach, it will find it's data faster and faster.
but not a solid solution yet no :)
Nice I was able to use this as an workaround. My code:
const { data } = await graphql(`
query {
allStrapiWorks {
nodes {
data {
id
attributes {
slug
name
description
}
}
}
}
}
`)
data.allStrapiWorks.nodes[0].data.forEach(node => {
const slug = node.attributes.slug
actions.createPage({
path: `/work/${slug}`,
component: require.resolve(`./src/templates/work-detail.js`),
context: {
workItem: node.attributes
},
})
})
}
In your component use pageContext to get the passed object:
function Product({ pageContext }) {
const { workItem} = pageContext
return (
<div>
Name: {workItem.name}
Description: {workItem.description}
</div>
)
}
Thank you so much! I was stuck on this issue for the last two weeks... This solved all my query issues!
I'm currently faced this issue, and figured out a way to get single data in the gatsby-graphql with new node like this:
graphQL
query Articles {
strapiArticle(data: {id: {eq: 3}}) {
data {
id
attributes {
publishDate
}
}
id
}
strapiArticles {
data {
attributes {
publishDate
}
id
}
id
}
}
data
{
"data": {
"strapiArticle": {
"data": {
"id": 3,
"attributes": {
"publishDate": "2022-02-10"
}
},
"id": "21e77627-27c5-5f52-b0c4-62aa23ccfcf9"
},
"strapiArticles": {
"data": [
{
"attributes": {
"publishDate": "2022-01-30"
},
"id": 1
},
{
"attributes": {
"publishDate": "2022-02-01"
},
"id": 2
},
{
"attributes": {
"publishDate": "2022-02-10"
},
"id": 3
}
],
"id": "Articles_undefined"
}
},
"extensions": {}
}
strapiArticles is the original node which the gatsby-source-strapi made for us.
strapiArticle is the one created with gatsby-node.js, and we can get single data with query variable $id
.
The workaround here is to get out the data (inside the array), and then generate a new node with Gatsby node API createNode
.
gatsby-node.js
module.exports.onCreateNode = async ({ node, actions, createNodeId, createContentDigest }) => {
const { createNode } = actions;
if(node.internal.type === "StrapiArticles") {
node.data.forEach(d => {
const newNode = {
data: d,
id: createNodeId(`StrapiArticle-${d.id}`),
parent: node.id,
children: [],
internal: {
type: "StrapiArticle",
contentDigest: createContentDigest(d)
},
};
createNode(newNode);
})
}
};
References
Gatsby Node APIs onCreateNode
Gatsby Actions createNode
Node Interface contentDigest
Node API Helper createContentDigest createNodeId
This is very annoying to be honest. Could you please let me know when we can expect a fix. Actually if it matches on two elements it is returning two sets of results.