1

Using:

$query = new WP_Query();

How do I filter to get records with titles OR content OR meta keys which contain a part of a string.

I currently have

$args=array(
          'order'=>'asc',
          'post_type' => $type,
          'post_status' => 'publish',
          'meta_query' => array(
                array(
                        'key'     => 'my_meta_key',
                        'value'   => sanitize_text_field($_GET["search"]),
                        'compare' => 'LIKE'
                    )
                ),
          'posts_per_page' => -1,
          'caller_get_posts'=> 1); 

Which is currently working perfectly but does not obvious filter by title and content as well.

  • Please note, this site is about WordPress, adding that your question is about WordPress is therefor useless. Also note, if you had debugging turned on, you would have noticed that caller_get_posts is depreciated for many many years now and should not be used. You should be using ignore_sticky_posts – Pieter Goosen Jun 7 '16 at 10:28
2

Such condition is impossible to express in current WP API. You can use search for title/content matches and meta query for LIKE matches on post meta, but there is no way to establish OR relationship between the two.

The closest API way would be two–stage query where you query IDs for two sets of results (one for search, one for meta), then query full data for their combination.

Outside of that it is realm custom SQL. Not impossible, but relatively hard to write and harder to maintain.

| improve this answer | |
  • Thanks a lot for the response.......I have decided to settle for searching by just the title WITH a like comparison.....can you please point me in the right direction – Lukesoft Jun 7 '16 at 11:18
  • See Search Parameter in Codex. – Rarst Jun 7 '16 at 11:19
0

I think this code can do what you want:

$q1 = get_posts(array(
    'post_type' => 'product',
    'post_status' => 'publish',
    'posts_per_page' => '-1',
    's' => get_search_query()
));
$q2 = get_posts(array(
    'post_type' => 'product',
    'post_status' => 'publish',
    'posts_per_page' => '-1',
    'meta_query' => array(
        array(
           'key' => '_sku',
           'value' => get_search_query(),
           'compare' => 'LIKE'
        )
     )
));
$merged = array_merge( $q1, $q2 );
$post_ids = array();
foreach( $merged as $item ) {
    $post_ids[] = $item->ID;
}
$unique = array_unique($post_ids);
if(!$unique){
    $unique=array('0');
}
$args = array(
    'post_type' => 'product',
    'posts_per_page' => '10',
    'post__in' => $unique,
    'paged' => get_query_var('paged'),
);
$wp_query = new WP_Query($args);
| improve this answer | |
0

You should just be able to tack on

's' => get_search_query()

to your existing query, no? As in:

$args=array(
      'order'=>'asc',
      'post_type' => $type,
      'post_status' => 'publish',
      'meta_query' => array(
            array(
                    'key'     => 'my_meta_key',
                    'value'   => sanitize_text_field($_GET["search"]),
                    'compare' => 'LIKE'
                )
            ),
      's' => get_search_query(),
      'posts_per_page' => -1,
      'caller_get_posts'=> 1); 

I use pretty much this exact approach to a database search where you can search last name or first name (stored as custom fields), and then choose to add in keywords which searches post content within posts that match the custom fields.

| improve this answer | |
0

I couldn't find a solution to look for multiple keywords that can be mixed in either post title, description AND/OR one or several metas, so I made my own addition to the search function.

All you is to add the following code in function.php, and whenever you us the 's' argument in WP_Query() and want it to search in one or several as well you simply add a 's_meta_keys' argument that is an array of the meta(s) key you want to search in:

/************************************************************************\
|**                                                                    **|
|**  Allow WP_Query() search function to look for multiple keywords    **|
|**  in metas in addition to post_title and post_content               **|
|**                                                                    **|
|**  By rAthus @ Arkanite                                              **|
|**  Created: 2020-08-18                                               **|
|**  Updated: 2020-08-19                                               **|
|**                                                                    **|
|**  Just use the usual 's' argument and add a 's_meta_keys' argument  **|
|**  containing an array of the meta(s) key you want to search in :)   **|
|**                                                                    **|
|**  Example :                                                         **|
|**                                                                    **|
|**  $args = array(                                                    **|
|**      'numberposts'  => -1,                                         **|
|**      'post_type' => 'post',                                        **|
|**      's' => $MY_SEARCH_STRING,                                     **|
|**      's_meta_keys' => array('META_KEY_1','META_KEY_2');            **|
|**      'orderby' => 'date',                                          **|
|**      'order'   => 'DESC',                                          **|
|**  );                                                                **|
|**  $posts = new WP_Query($args);                                     **|
|**                                                                    **|
\************************************************************************/
add_action('pre_get_posts', 'my_search_query'); // add the special search fonction on each get_posts query (this includes WP_Query())
function my_search_query($query) {
    if ($query->is_search() and $query->query_vars and $query->query_vars['s'] and $query->query_vars['s_meta_keys']) { // if we are searching using the 's' argument and added a 's_meta_keys' argument
        global $wpdb;
        $search = $query->query_vars['s']; // get the search string
        $ids = array(); // initiate array of martching post ids per searched keyword
        foreach (explode(' ',$search) as $term) { // explode keywords and look for matching results for each
            $term = trim($term); // remove unnecessary spaces
            if (!empty($term)) { // check the the keyword is not empty
                $query_posts = $wpdb->prepare("SELECT * FROM {$wpdb->posts} WHERE post_status='publish' AND ((post_title LIKE '%%%s%%') OR (post_content LIKE '%%%s%%'))", $term, $term); // search in title and content like the normal function does
                $ids_posts = [];
                $results = $wpdb->get_results($query_posts);
                if ($wpdb->last_error)
                    die($wpdb->last_error);
                foreach ($results as $result)
                    $ids_posts[] = $result->ID; // gather matching post ids
                $query_meta = [];
                foreach($query->query_vars['s_meta_keys'] as $meta_key) // now construct a search query the search in each desired meta key
                    $query_meta[] = $wpdb->prepare("meta_key='%s' AND meta_value LIKE '%%%s%%'", $meta_key, $term);
                $query_metas = $wpdb->prepare("SELECT * FROM {$wpdb->postmeta} WHERE ((".implode(') OR (',$query_meta)."))");
                $ids_metas = [];
                $results = $wpdb->get_results($query_metas);
                if ($wpdb->last_error)
                    die($wpdb->last_error);
                foreach ($results as $result)
                    $ids_metas[] = $result->post_id; // gather matching post ids
                $merged = array_merge($ids_posts,$ids_metas); // merge the title, content and meta ids resulting from both queries
                $unique = array_unique($merged); // remove duplicates
                if (!$unique)
                    $unique = array(0); // if no result, add a "0" id otherwise all posts wil lbe returned
                $ids[] = $unique; // add array of matching ids into the main array
            }
        }
        if (count($ids)>1)
            $intersected = call_user_func_array('array_intersect',$ids); // if several keywords keep only ids that are found in all keywords' matching arrays
        else
            $intersected = $ids[0]; // otherwise keep the single matching ids array
        $unique = array_unique($intersected); // remove duplicates
        if (!$unique)
            $unique = array(0); // if no result, add a "0" id otherwise all posts wil lbe returned
        unset($query->query_vars['s']); // unset normal search query
        $query->set('post__in',$unique); // add a filter by post id instead
    }
}

Example use:

$search= "kewords to search";

$args = array(
    'numberposts'   => -1,
    'post_type' => 'post',
    's' => $search,
    's_meta_keys' => array('short_desc','tags');
    'orderby' => 'date',
    'order'   => 'DESC',
);

$posts = new WP_Query($args);

This example will look for the keywords "kewords to search" in post titles, descriptions, and meta keys 'short_desc' and 'tags'.

Keywords can be found in one or several of the fileds, in any order, it will return any post that has all the keywords in any of the designated fields.

You can obiously force the search in a list of meta keys you include in the fonction and get rid of the extra agruments if you want ALL search queries to include these meta keys :)

Hope that will help anyone who face the same issue I did!

| improve this answer | |

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.