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

Your Answer

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

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