Borje
Borje

Reputation: 255

Filtering on an ACF Post Object-field in wordpress in Gatsby and GraphQL

This is follow up question on Querying wordpress with meta queries from Gatsby

After a bit debugging I've gathered, and please correct me if I'm wrong, that Gatsby on build downloads the entire data structure and caches it. So all the GraphQL queries are performed against the cache. This makes all adjustments I try to make to wordpress (for example https://www.wpgraphql.com/2020/04/14/query-posts-based-on-advanced-custom-field-values-by-registering-a-custom-where-argument/) useless. I'm confined to using the filter argument for my GraphQL queries in Gatsby.

Consider the following query:

query Test {
  allWpPage(filter: {pagesGeo: {}}) {
    edges {
      node {
        pagesGeo {
          genericPage {
            ... on WpPage {
              id
            }
          }
          hreflangValue
        }
      }
    }
  }
}

In this case I want to filter on genericPage, but it's not in the list of available filters in the GraphiQL query tester.

In Wordpress the custom field generic_page is defined with the help of advanced custom fields and it's of the field type 'Post Object'. As you can see I'm able to query the field just fine, and it would be easy for me to create a meta query in Wordpress to filter on the field. It would looks something like:

$query_args['meta_query'] = [
    "relation" => "OR",
    [
        'key' => 'generic_page',
        'value' => $postObjectId,
        'compare' => '='
    ],
    [
        'key' => 'generic_page',
        'value' => $postObjectId2,
        'compare' => '='
    ],
];

Is there a way to make it possible for me to filter on genericPage in Gatsby?

If not, are there any alternative solutions for me to extract the data I need?

Upvotes: 4

Views: 2817

Answers (1)

Sally CJ
Sally CJ

Reputation: 15620

After a bit debugging I've gathered, and please correct me if I'm wrong, that Gatsby on build downloads the entire data structure and caches it. So all the GraphQL queries are performed against the cache.

Yes, that's correct.

And I don't know much about Gatsby or GraphQL coding, but this is what I did and it worked quite well for me:

  1. I created a Gatsby site using the "WordPress blog" starter: https://github.com/gatsbyjs/gatsby-starter-wordpress-blog

  2. Then on my WordPress site, I installed these plugins: ACF (free version, v5.10.2), WP Gatsby v1.1.3, WP GraphQL v1.6.4, "WPGraphQL for Advanced Custom Fields" v0.5.3, and (just for testing) WPGraphQL Meta Query v0.1.0

  3. Then I created an ACF field group named "Pages GEO":

    • In the GraphQL meta box, I set "Show in GraphQL" to "Yes" and then I set "GraphQL Field Name" to pagesGeo (which is what you used, right?)

    • Then I created a Post Object field named "Generic Page" (generic_page) and then I set "Show in GraphQL" to "Yes"

  4. And then of course, I created/edited some Pages (i.e. post type page) and then selected a "Generic Page" for those Pages.

So regarding this:

In this case I want to filter on genericPage, but it's not in the list of available filters in the GraphiQL query tester.

I was not able to add filter.pagesGeo.genericPage, but I managed to filter by that field (i.e. filter.genericPage) by doing this:

I registered my very own custom WP GraphQL field named genericPage

  1. In my theme functions.php, I added:

    • The code is based on the one here.
    add_action( 'graphql_register_types', function() {
        register_graphql_field( 'Page', 'genericPage', [
            'type'        => 'Integer',
            'description' => 'generic_page meta value',
            'resolve'     => function( \WPGraphQL\Model\Post $post ) {
                return (int) get_post_meta( $post->databaseId, 'generic_page', true );
            }
        ] );
    });
    
  2. Then in GraphiQL IDE (at http://localhost:8000/__graphql), I ran this query:

    Screenshot

    • So in the above query, I filtered the posts by the generic_page meta, where I queried for posts where the meta value (i.e. the post ID, or databaseId in GraphQL) is 2 or 82.

    • And I used the in comparator, but you could just use any other comparator that suits your query. See https://www.gatsbyjs.com/docs/query-filters/#supported-comparators

  3. And the result was:

    Screenshot 2

    • So as you could see, for each node/post (in data.allWpPage.nodes), the root genericPage matches the pagesGeo.genericPage.databaseId.

Additional Notes

I used the gatsby develop command which (if I was not mistaken) rebuilds the cache, but if necessary, the cache can be cleared manually — see https://www.gatsbyjs.com/docs/build-caching/#clearing-cache.

Upvotes: 6

Related Questions