Understanding the Limitations: WPGraphQL for ACF, and Meta Queries Support

Francis Agulto Avatar

·

In this article, we will take a look at Meta Queries in WPGraphQL and ACF. If you are not familiar with Meta Data in WordPress, it is essentially supplemental information about objects. In the case of WordPress, meta data is additional information associated with objects native to WordPress, such as posts, users, comments, terms, or custom post types and taxonomies registered to WordPress using tools like ACF.

Given the many-to-one relationship of metadata in WordPress, your options are fairly limitless. You can have as many meta fields per object as you wish, and you can store just about anything as meta.

Meta data is a powerful tool in WordPress development, as it allows for the extension of standard data structures to accommodate the specific needs of a website without altering core database schemas. This is particularly important in headless WordPress setups, where custom fields (post meta) can be exposed via WPGraphQL to be consumed by the frontend application.

The WordPress Database

While there is incredible utility in the flexibility of storing arbitrary data to supplement WordPress objects, the flexibility can come at a cost.

In order to understand the issue that querying by meta presents, let’s take a look at the WordPress database.

WordPress relies on a MySQL database, a robust and widely-used relational database management system. This database stores all the content and settings of a WordPress site, structured into several tables that handle posts, pages, comments, users, and meta-information, among others. The core of content storage lies within the wp_posts table, which houses not just posts but also pages, custom post types, and attachments. Each entry in this table is uniquely identified by an ID column, serving as the primary key. This ID is auto-incremented for each new entry, ensuring uniqueness and facilitating efficient data retrieval.

The efficiency of querying the WordPress database, particularly when fetching posts by their ID, is largely due to how SQL databases are designed to index primary keys. When a query requests a post by its ID, the database’s indexing system allows for a rapid, direct access path to the sought-after record, significantly reducing the time and computational resources needed compared to scanning the entire table.

For reference, here is an image of the wp_posts data table:

The Meta Query Issue in WP Databases

Meta Queries in WordPress provide a way for querying posts based on meta data, but they can introduce significant performance challenges, particularly on large-scale sites like newspapers or media outlets, where meta data can amass to millions of rows. Each meta key-value pair in WordPress is stored in the wp_postmeta table, which has a flexible structure allowing for virtually any type of data to be stored. This flexibility comes with a cost. Since meta keys are not strictly defined and meta values can contain anything from JSON strings to URLs, there is no practical way to enforce indexing strategies that would normally optimize query performance.  It is like the wild-west. 🤠

As a result, when a Meta Query is executed, it will scan of all the rows in the wp_postmeta table, which is incredibly inefficient. This is like trying to find a needle in a haystack; the query must sift through potentially millions of rows to locate the desired records. In the context of a high-traffic site with extensive meta data, this can lead to slow query execution times and a heavy load on the database server, ultimately impacting the user experience and shutting the site down.

This is the major reason why this functionality is not part of the core WPGraphQL plugin.

Here is an image of a sample meta query table:

Now, this is just a normal demo site with not much post data.  But imagine a local or national media or newspaper site with millions of rows of meta.

Performance Degradation in Meta Queries

When considering that these operations might not be merely occasional but could be a regular part of the site’s operation, it becomes clear that Meta Queries can become a bottleneck for database performance which leads to slow queries and bad user experience.

Solutions to the Meta Query Issue

The first way to address the issue is to simply accept it. You could choose to overlook the performance impact and accept the slower query execution. For most WordPress sites, which are small enough, this may be so inconsequential that it doesn’t significantly affect your experience.

Utility Taxonomies

Leveraging a private taxonomy instead of post meta can lead to substantial performance improvements in headless WordPress setups. By tagging posts with a non-public taxonomy, you can sidestep the costly operations associated with meta queries.

For example:

new WP_Query([
  'post_type' => 'post',
  'tax_query' => [
     [
        'taxonomy' => 'text_field_utility_tax',
        'field' => 'title',
        'terms' => $search_term,
        'operator' => 'IN',
     ]
  ]
]);

Code language: PHP (php)

Whenever the “text_field” is updated, it is synced to the text_field_utility_tax and associated with the post.  Then users could query via tax query instead of meta_query to avoid performance issues.

With this utility taxonomy in place, searching and organizing posts as well as UI’s for ACF fields becomes a taxonomy query, which is inherently more efficient than querying for wild meta-keys. 

The values under the hood perform better when a query is filtered via tax query. 

You can read more about the concept of Utility Taxonomies here: https://tomjn.com/2018/03/16/utility-taxonomies/

Other Solutions

Another option to filter data by Meta Values in WPGraphQL would be to write your own custom code to handle this. This would require registering field(s) to the Schema to allow input from the query, then filtering the resolver(s) to use that input and pass it to the underlying WP_Query (or equivalent) to filter the data being queried for.

There is also an extension WPGraphQL Meta Query that adds the ability to filter connections via meta queries.  Use these both at your own discretion and risk.  The WPGraphQL Meta Query extension is not actively maintained nor are there current plans to introduce this functionality to core WPGraphQL.

Conclusion

When developing apps and sites with large amounts of meta data in a headless WordPress environment using ACF and WPGraphQL, it is crucial to be aware of and understand the issues related to Meta Queries. I hope this article has provided you with a clearer understanding of the causes of these issues and how you can address them, albeit at your own risk.

Here are a few more links if you are interested in reading more about the subject:

https://tomjn.com/2017/02/27/not-post-meta-bad/

https://tomjn.com/2016/12/05/post-meta-abuse/

As always, stoked to hear your feedback and any questions you might have on headless WordPress! Hit us up in our Discord!