0

I have created a custom post type service-provider with custom taxonomies region and service-category - By itself, this search works as expected BUT I want to also search on an ACF field.

I have an ACF field on the service-provider post type called organisation

I have added a meta_query with relation = OR to search with the keyword and find a match either in the post content OR the ACF field.

I have a post with Title = "Accommodation Service" and ACF Field "organisation" = "Dawn Inc"

I want the search to show results where the keyword matches either the post title or the acf field.

Here is my query:

<?php
// Handle form submission
$keyword = isset( $_GET['keyword'] ) ? sanitize_text_field( $_GET['keyword'] ) : '';
$region = isset( $_GET['region'] ) ?  array_map('sanitize_text_field', $_GET['region']) : array();
$service_category = isset( $_GET['service-category'] ) ? array_map('sanitize_text_field', $_GET['service-category']) : array();

if ( !empty($keyword) || !empty($service_category) ) :

    $args = array(
        'post_type'      => 'service-provider',
        'posts_per_page' => -1,
        's'              => $keyword,
        'meta_query'     => array(
            'relation'    => 'OR',
            array(
                'key'     => 'organisation', 
                'value'   => $keyword,
                'compare' => 'LIKE',
            )
        ),
    );

    if ( ! empty( $region ) ) 
    {
        $args['tax_query'][] = array(
                'taxonomy' => 'region',
                'field'    => 'slug',
                'terms'    => $region,
        );
    }

    if ( ! empty( $service_category ) ) 
    {
        $args['tax_query'][] = array(
                'taxonomy' => 'service-category',
                'field'    => 'slug',
                'terms'    => $service_category,
        );
    }

    $query = new WP_Query( $args ); ?>

When I search for "dawn" I get no results. So I dumped the $query to see the SQL and this is what I got:

SELECT   wp_posts.*
FROM wp_posts  
INNER JOIN wp_postmeta 
    ON ( wp_posts.ID = wp_postmeta.post_id )
WHERE 1=1  
    AND (((wp_posts.post_title LIKE '%dawn%') OR (wp_posts.post_excerpt LIKE '%dawn%') OR (wp_posts.post_content LIKE '%dawn%')))  
    AND ( ( wp_postmeta.meta_key = 'organisation' AND wp_postmeta.meta_value LIKE '%dawn%' ) ) 
    AND ((wp_posts.post_type = 'service-provider' AND (wp_posts.post_status = 'publish' OR wp_posts.post_status = 'acf-disabled' 
OR wp_posts.post_status = 'private')))
GROUP BY wp_posts.ID
ORDER BY wp_posts.post_title LIKE '%dawn%' DESC, wp_posts.post_date DESC

I see that the meta_query is performing an AND relation.

When I run this query straight in MySQL I get no results BUT, if I change the AND to an OR on this line:

FROM:

AND ( ( wp_postmeta.meta_key = 'organisation' AND wp_postmeta.meta_value LIKE '%dawn%' ) )

TO:

OR ( ( wp_postmeta.meta_key = 'organisation' AND wp_postmeta.meta_value LIKE '%dawn%' ) )

I get the result I am expecting to see...

So, if I have already set the meta_query to OR and it is giving me this result - how to I fix this query to give me the results I expect?

1 Answer 1

1

From the developer docs:

relation (string) – The logical relationship between each inner meta_query array when there is more than one. Possible values are ‘AND’, ‘OR’. Do not use with a single inner meta_query array.

(Emphasis mine).

It's a bit hacky, but you could run a separate query against the meta field, then merge the results into the default search query before The Loop thus:

$wp_query->posts = array_unique ( array_merge( $wp_query->posts, $meta_query->posts ) SORT_REGULAR );
$num = count( $wp_query->posts );
// these two should be the same in this case because posts_per_page is -1
$wp_query->post_count = $num;
$wp_query->found_posts = $num;
1
  • Thanks. I like the ingenuity. Commented May 6 at 2:57

Not the answer you're looking for? Browse other questions tagged or ask your own question.