6

I have a site using Advanced Custom Fields to create and store various bits of relevant info. These need to be included in the main general search, which by default only searches the title and main content.

I've found plenty of info about getting search results based on specific bits of postmeta, but I have an issue with that. There are a potentially unlimited amount of potential fields in postmeta to search.

The solution could either search anything in postmeta or anything with a meta_key that matches this regex: content_section_[0-9]{1,4}_content_.{2,8}

Example meta_keys to match are:

content_section_0_content_title
content_section_0_content_title
content_section_4_content_subtitle
content_section_8_content_text

Any way that I can alter the fields searched to include the postmeta would be very much appreciated.

  • and the question is? – Naoise Golden Dec 8 '11 at 21:31
  • Searching in Wordpress doesn't search data from the post meta - it only searches the title and content fields. I'll update the main question to clarify. – Jodi Warren Dec 9 '11 at 0:53
2

If your up for using a plugin, Relevanssi - A Better Search might be worth trying out.

The standard (free) version supports searching post meta.

10

Add this to your plugin or functions.php file of your theme. The example below will include 'your_key' in search. You can include all your keys by repeating the array.

function me_search_query( $query ) {
  if ( $query->is_search ) {
    $meta_query_args = array(
      array(
        'key' => 'your_key',
        'value' => $query->query_vars['s'] = '',
        'compare' => 'LIKE',
      ),
    );
    $query->set('meta_query', $meta_query_args);
  };
}
add_filter( 'pre_get_posts', 'me_search_query');
  • 5
    This will only match posts that matches the search term in title/content and in the meta field which is not how a full text search typically works. – David Jul 9 '17 at 16:16
5

This function should work, even after WP 4.8.3 security update.

Usage:

// Do this in functions.php

add_meta_field_to_search_query('right_data');
add_meta_field_to_search_query('extra_search_terms');

Implementation:

/* ADD META FIELD TO SEARCH QUERY */

function add_meta_field_to_search_query($field){
  if(isset($GLOBALS['added_meta_field_to_search_query'])){
    $GLOBALS['added_meta_field_to_search_query'][] = '\'' . $field . '\'';

    return;
  }

  $GLOBALS['added_meta_field_to_search_query'] = array();
  $GLOBALS['added_meta_field_to_search_query'][] = '\'' . $field . '\'';

  add_filter('posts_join', function($join){
      global $wpdb;

      if (is_search()){    
          $join .= " LEFT JOIN $wpdb->postmeta ON $wpdb->posts.ID = $wpdb->postmeta.post_id ";
      }

      return $join;
  });

  add_filter('posts_groupby', function($groupby){
      global $wpdb;

      if (is_search()) {    
          $groupby = "$wpdb->posts.ID";
      }

      return $groupby;
  });

  add_filter('posts_search', function($search_sql){
      global $wpdb;

      $search_terms = get_query_var('search_terms');

      if(!empty($search_terms)){
        foreach ($search_terms as $search_term){
            $old_or = "OR ({$wpdb->posts}.post_content LIKE '{$wpdb->placeholder_escape()}{$search_term}{$wpdb->placeholder_escape()}')";
            $new_or = $old_or . " OR ({$wpdb->postmeta}.meta_value LIKE '{$wpdb->placeholder_escape()}{$search_term}{$wpdb->placeholder_escape()}' AND {$wpdb->postmeta}.meta_key IN (" . implode(', ', $GLOBALS['added_meta_field_to_search_query']) . "))";
            $search_sql = str_replace($old_or, $new_or, $search_sql);
        }
      }

      $search_sql = str_replace( " ORDER BY ", " GROUP BY $wpdb->posts.ID ORDER BY ", $search_sql );

      return $search_sql;
  });
}

Several people have done this in different ways:

http://websmartdesign.nz/searching-structured-post-data-with-wordpress/ https://adambalee.com/search-wordpress-by-custom-fields-without-a-plugin/

2

This is an improved Ahmed's answer:

function me_search_query( $query ) {
  if ( $query->is_search ) {
    $meta_query_args = array(
      array(
        'key' => 'your_key',
        'value' => $query->query_vars['s'],
        'compare' => 'LIKE',
      ),
    );
    $query->set('meta_query', $meta_query_args);
    add_filter( 'get_meta_sql', 'me_replace_and_with_or' );
  };
}

function me_replace_and_with_or( $sql ) {
    if ( 1 === strpos( $sql['where'], 'AND' ) ) {
        $sql['where'] = substr( $sql['where'], 4 );
        $sql['where'] = ' OR ' . $sql['where'];
    }

    //make sure that this filter will fire only once for the meta query
    remove_filter( 'get_meta_sql', 'me_replace_and_with_or' );
    return $sql;
}

add_filter( 'pre_get_posts', 'me_search_query');

The problem is that WordPress generates meta query with "AND" operator, and it would show only posts which have search string in both places - title AND meta, or content AND meta. So, we need to create an additional filter to change "AND" to "OR" (and then remove that filter to not break anything else).

0

I'm not sure, but to grab all the custom field keys/values for the default search would require a database call using wpdb.

The alternative plugin besides the ones goto10 mentioned are a much simpler solution. Search Everything, WP Custom Fields Search

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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