GraphQL disable filtering if filter variable is empty
Asked Answered
B

3

5

I have a Gatsby GraphQL query for a list of posts ordered by date and filtered by category.

{
  posts: allContentfulPost(
    sort: {fields: [date], order: DESC},
    filter: {category: {slug: {eq: $slug}}}
  ) {
    edges {
      node {
        title {
          title
        }
        date
      }
    }
  }
}

Right now when $slug is the empty string "", I get

{
  "data": {
    "posts": null
  }
}

Is there a way to get all posts instead?

Bergschrund answered 26/6, 2018 at 16:38 Comment(4)
Could you try setting $slug to null instead of "" in that case?Palladian
@FabianSchultz I did. Same result unfortunately, both with and without quotes around null.Bergschrund
did you found a solution to your problem?Frazzle
Not really. It ceased to be a problem for me because for unrelated reasons I opted to always query all posts and do the filtering on the fly with JS.Bergschrund
H
6

You can use the regex filter to your advantage. If you pass an empty expression, then all posts will be returned because everything will match.

query Posts($slugRegex: String = "//"){
  posts: allContentfulPost(
    sort: {fields: [date], order: DESC},
    filter: {category: {slug: {eq: $slugRegex}}}
  ) {
    # Rest of the query.
  }
}

By default, all posts will be returned (the $slugRegex is an empty regex if nothing was passed). When the $slugRegex becomes a meaningful expression, then only matching posts will show up.

As for passing the value, I'm assuming you're using gatsby-node.js to create pages. In that case, it's as simple as that:

// gatsby-node.js

exports.createPages = async ({ actions }) => {
  const { createPage } = actions

  // Create a page with only "some-slug" posts.
  createPage({
    // ...
    context: {
      slugRegex: "/some-slug/"
    }
  })

  // Create a page with all posts.
  createPage({
    // ...
    context: {
      // Nothing here. Or at least no `slugRegex`.
    }
  })
}
Huskamp answered 17/8, 2019 at 10:1 Comment(1)
Your answer helped me a lot figuring out a solution. In my case, I used a regex too but in the filter I've use the term regex instead of eq, so based on your example it's: filter: {category: {slug: {regex: $slugRegex}}}Intelligencer
P
2

If anyone requires a solution for other systems than Gatsby this can be accomplished using @skip and @include.

fragment EventSearchResult on EventsConnection {
  edges {
    cursor
    node {
      id
      name
    }
  }
  totalCount
}

query Events($organizationId: UUID!, $isSearch: Boolean!, $search: String!) {
  events(condition: { organizationId: $organizationId }, first: 100)
    @skip(if: $isSearch) {
    ...EventSearchResult
  }
  eventsSearch: events(
    condition: { organizationId: $organizationId }
    filter: { name: { likeInsensitive: $search } }
    first: 100
  ) @include(if: $isSearch) {
    ...EventSearchResult
  }
}

Then in your client code you would provide search and isSearch to the query and get your events like:

const events = data.eventsSearch || data.events
Prosimian answered 31/1, 2021 at 5:38 Comment(0)
S
1

It's not possible with this query, even @skip/@include directives won't help because you can't apply them on input fields.

I would suggest to either adjust the server side logic so that null in the 'eq' field will ignore this filter or either to edit the query being sent (less favorable imo).

It seems that the graphql schema that you work against lacks the filtering support you need..

Selfgratification answered 5/7, 2018 at 15:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.