gatsby-source-strapi icon indicating copy to clipboard operation
gatsby-source-strapi copied to clipboard

Graphql filter on one type doesn't work

Open mariovde-IIO opened this issue 3 years ago • 14 comments

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.

mariovde-IIO avatar Jan 06 '22 12:01 mariovde-IIO

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 avatar Jan 10 '22 22:01 jan-wagenaar

@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...

mariovde-IIO avatar Jan 11 '22 08:01 mariovde-IIO

@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😭

zhanghui-space avatar Jan 11 '22 11:01 zhanghui-space

@gzhanghui actually happy to see I'm not the only one :)

mariovde-IIO avatar Jan 11 '22 11:01 mariovde-IIO

@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 avatar Jan 11 '22 20:01 jan-wagenaar

@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...

mariovde-IIO avatar Jan 11 '22 20:01 mariovde-IIO

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/

jan-wagenaar avatar Jan 11 '22 20:01 jan-wagenaar

It's for a page, off course, but gatsby node api needs the same query as far as I know...

mariovde-IIO avatar Jan 11 '22 20:01 mariovde-IIO

That right, but in the gatsby-node.js code you may be able to implement custom logic.

image

I will try it for myself. Ofcourse, this is a temporary workaround....

jan-wagenaar avatar Jan 11 '22 20:01 jan-wagenaar

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 :)

mariovde-IIO avatar Jan 11 '22 20:01 mariovde-IIO

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>
  )
}

jan-wagenaar avatar Jan 11 '22 21:01 jan-wagenaar

Thank you so much! I was stuck on this issue for the last two weeks... This solved all my query issues!

shelleyphant avatar Jan 17 '22 21:01 shelleyphant

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

Yuan0100 avatar Feb 10 '22 06:02 Yuan0100

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.

gowthamik14 avatar Jul 20 '22 11:07 gowthamik14