1

I am trying to select records that have a custom field value that matches a search condition but the result is always all records

To register the custom field for my post type I am using the following code

register_post_meta(
  'my_post_type',
  'my_data',
  array(
    'show_in_rest' => true,
    'single' => true,
    'type' => 'integer',
  )
)

To query the posts:

const data = useSelect((select) => {
  const metaQuery = [
    {
      key: 'my_data',
      value: [50, 100],
      compare: 'BETWEEN',
      type: 'NUMERIC'
    }
  ];
  return select(coreDataStore).getEntityRecords('postType', 'my_post_type', { meta_query: metaQuery });
});

but I am always receiving all records with my custom posts and zero errors or warnings. The metadata field is presented in the results. Generated request to the server contains the meta_query part, but it is url encoded. This is probably a reason why meta_query is ignored.

What did I miss?

2
  • 1
    while not the solution to this specific question, you may want to register a taxonomy that has bucketed terms e.g. 50-100 then assign those terms automatically in PHP. meta_query has very poor performance and doesn't scale with traffic or post count getting significantly slower/heavier on the database, which is why categories/tags/taxonomies aren't stored as post meta. That doesn't mean you have to give up storing precise integers in meta, but storing buckets in a taxonomy gives you the best of both worlds ( and it's easier to query the taxonomy in WP Data too ) Commented Dec 3, 2024 at 22:14
  • @TomJNowell Good advice. This is my "plan B" ) Commented Dec 3, 2024 at 22:48

1 Answer 1

1

It appears that REST API doesn't support all the meta_query parameters that WP_Query does. Only the basic meta queries with some comparison operators are supported.

Therefore we need to make one of workarounds to get what we want:

  • Add some REST API Filter to our theme/plugin
add_filter('rest_{post_type}_query', function($args, $request) {
    $params = $request->get_params();
    if(isset($params['meta_compare'])) {
        $args['meta_query'] = [[
            'key'     => $params['meta_key'],
            'value'   => $params['meta_value'],
            'compare' => $params['meta_compare'],
            'type'    => $params['meta_type'] ?? 'CHAR'
        ]];
    }
    return $args;
}, 10, 2);
  • Create some custom REST Endpoints
add_action('rest_api_init', function() {
  register_rest_route('myplugin/v1', '/posts-with-meta/', array(
    'methods' => 'GET',
    'callback' => 'my_custom_meta_query',
    'permission_callback' => function() { return true; }
  ));
});

function my_custom_meta_query($request) {
  $args = array(
    'post_type' => 'my_post_type',
    'meta_query' => array(
      array(
        'key' => 'my_data',
        'value' => array(50, 100),
        'compare' => 'BETWEEN',
        'type' => 'NUMERIC'
      )
    )
  );
  
  $query = new WP_Query($args);
  return rest_ensure_response($query->posts);
}

Then query it from our JavaScript:

const data = useSelect((select) => {
  return select(coreDataStore).getEntityRecords('root', 'myplugin/v1/posts-with-meta');
});

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.