2

I'm making a custom post meta search with the pre_get_posts function in my Divi child theme functions.php file. The problem is that the final query gathers not only the results for my custom post field (named 'autor') but other fields like 'post_title' and 'post_post' which I have not included.

That's the resulting query with the troublesome line highlighted in strong:

SELECT SQL_CALC_FOUND_ROWS ebj_posts.ID FROM ebj_posts INNER JOIN ebj_term_relationships ON (ebj_posts.ID = ebj_term_relationships.object_id) INNER JOIN ebj_postmeta ON ( ebj_posts.ID = ebj_postmeta.post_id ) INNER JOIN ebj_postmeta AS mt1 ON ( ebj_posts.ID = mt1.post_id ) WHERE 1=1 AND ( ebj_term_relationships.term_taxonomy_id IN (456) ) AND (((ebj_posts.post_title LIKE '%Abulafia%') OR (ebj_posts.post_content LIKE '%Abulafia%'))) AND ( ebj_postmeta.meta_key = 'autor' AND ( ( mt1.meta_key = 'autor' AND CAST(mt1.meta_value AS CHAR) LIKE '%Abulafia%' ) ) ) AND ebj_posts.post_type IN ('post', 'page', 'attachment', 'project', 'ref_bib') AND ((ebj_posts.post_status = 'publish')) GROUP BY ebj_posts.ID ORDER BY ebj_postmeta.meta_value ASC LIMIT 0, 30"

As you can see the word 'Abulafia' is searched in the post_title and post_content fields, which is not intended.

This line in bold with the AND arguments come from WP > wp-includes > query line 2196:

$search .= $wpdb->prepare( "{$searchand}(($wpdb->posts.post_title $like_op %s) $andor_op ($wpdb->posts.post_content $like_op %s))", $like, $like );

because when I comment these line in the wordpress core code the problem vanish.

That's my code in functions.php:

function filtra_inici( $query ){
global $wp;
if ( ( is_archive() ) && $query->is_main_query() && !is_admin() ) {
  if ($query->is_search && isset($_GET['search-type']) && $_GET['search-type'] == 'autor') {
    $query->set( 'post_type', 'ref_bib');
    $query->set( 'post_status', 'publish');
    $query->set( 'orderby', 'meta_value');
    $query->set( 'meta_key', 'autor' );
    $query->set( 'order', 'ASC' );
    $meta_query = array('relation' => 'AND');
     array_push( $meta_query, array(
      'key' => 'autor',
      'value' => $query->query_vars['s'],
      'compare' => 'LIKE'
     ));
    $query->set( 'meta_query', $meta_query);
  } 
}// end is_archive
}

Thanks!

5
  • There's no way to retrieve the post meta for a handful of posts, without retrieving the posts themselves, the purpose of WP_Query is to retrieve posts, and that's exactly what it's doing, and that's the job of the main query. What you're seeing is expected behaviour
    – Tom J Nowell
    Apr 17, 2016 at 19:02
  • Thanks for your anwser Tom, but i'd like to intrecept in some way this query, by means of filter or something of the like. Probalby it's possible because there is plugins that get it done. Apr 17, 2016 at 19:21
  • Queries can be intercepted using the pre_get_posts filter, but lets say that you did indeed make WP_Query retrieve only the post meta, how would you pull that data out? WP_Query deals with WP_Post objects, that information is necessary. Even if you managed it, it would screw up any other code running on that page, and have unpredictable results. What you're trying to do is not the way things are meant to work, why is it you need the main query to fetch the meta for the posts and only the meta?
    – Tom J Nowell
    Apr 17, 2016 at 19:54
  • Well, what I want is get rid of this piece of code in the query SQL: AND (((ebj_posts.post_title LIKE '%Abulafia%') OR (ebj_posts.post_content LIKE '%Abulafia%'))). You see? the word "Abulafia" is searched in post_title and post_content fields when that is not intended. Apr 17, 2016 at 22:20
  • I understand that, but I think you've misunderstood my request for clarification, it's clear that you're trying to optimise something, but that something doesn't make very much sense, and you've provided little context, which is important. We need to understand what you're originally tried to do if we're to optimise it, what does this page actually do? Your question implies you have a very strange setup, and that you're simply doing it wrong, and now you're trying to optimise that, but you've shown no context
    – Tom J Nowell
    Apr 18, 2016 at 1:56

3 Answers 3

2

Create a another filter to remove post title and post content remove search terms try this if this helpful for you

add_filter( 'posts_search', 'custom_post_search_author_do', 10, 2 );

function custom_post_search_author_do($search, $query ){
  if(  ! empty($search) 
       && $query->is_main_query() 
       && !is_admin() 
       && isset($_GET['search-type'])
       && $_GET['search-type'] == 'autor'
  )
  $search = '';
  return $search;
}
2
  • That's fantastic! it worked! - The problem now is that the query are getting results form others custom post meta. But that's another matter and you get my question correctly anwsered. Thanks! - I'm sorry because I don't have enough reputation to score you. Apr 18, 2016 at 10:55
  • np it is not matter for reputation score. I want to solve your issue. If this answer is really helpful for you, only accept this answer else leave it. Apr 18, 2016 at 13:41
1

SOLVED!

In response to @tomjnowell : Yep! you are right, I'm not giving enough details nor context, sorry. I'm not used to post questions here, nor the english is my mother tongue, as you can see. So thanks to be so patient as to help me.

What I wanted

What I intended is to make a search by several post meta AND, optionally, ALL the post meta PLUS the post_title in a custom post type called ref_bib.

You can see the thing in action in this site about the Borgia family (mainly in catalan).

As you'll notice, initially there is several forms: the first to perform a general search (in custom post meta and post_title) and four more for the rest of options (yes, you are right: it can be simplified. I'll do).

Actually thanks to user5200704 I've made some research here and there and found finally something which is working pretty well for me (though not in a total and exhilarating happiness, as I'll probably explain in another question).

What I've got

In case somebody is interested, here is the code.

That's the search form (there is one for each post meta in the first version of the code, later I'll use a dropdown to make it sexier) :

<form method="get" id="searchform"  class="searchform" action="http://www.elsborja.cat/cat_bib/general/">
<div class="cercadiv">
<input type="text" value="" name="s" id="s" />
<input type="hidden" name="search-type" value="autor" />
<input id="cercabib" class="eb_submit" name="submit" type="submit" value="Cerca" />
</div>
</form>

And now the code in "functions.php":

add_filter('pre_get_posts', 'filtra_inici', 10, 2);

function filtra_inici( $query )
{

  global $wp;
  if ( ( is_archive() ) && $query->is_main_query() && !is_admin() ) {

if ( strpos(  $wp->query_vars['category_name'], 'revista-borja' ) !== false ) {
  $query->set( 'orderby', 'date');
  $query->set( 'order', 'ASC' );
}

if (
  $query->is_search
  && isset($_GET['search-type'])
  && $_GET['search-type'] == 'bibliografia'
) {
  $query->set( 'post_status', 'publish');
  $query->set( 'post_type', 'ref_bib');
}

if (
  $query->is_search
  && isset($_GET['search-type'])
  && 'bibliografia' !== $_GET['search-type']
) {

  $camp = $_GET['search-type'];

  if ($camp == 'general') {
    $custom_fields = array('autor', 'publicacio', 'edito', 'observacions');
  }else {
    $custom_fields = array( $camp);
  }

  $searchterm = $query->query_vars['s'];
  // we have to remove the "s" parameter from the query, because it will prevent the posts from being found
  $query->query_vars['s'] = "";
  if ($searchterm != "") {
    $meta_query = array('relation' => 'OR');
    foreach ($custom_fields as $cf) {
      array_push($meta_query, array(
          'key' => $cf,
          'value' => $searchterm,
          'compare' => 'LIKE'
        ));
    }
    $query->set("meta_query", $meta_query);
    $query->set( 'post_type', 'ref_bib');
    $query->set( 'post_status', 'publish');
  };
}
}// end is_archive
}

An this filter modifies the where clause to add the search for the post_title in case the user wants to make a general search which includes ALL the custom meta AND the post_title.

add_filter( 'posts_where', 'titol_posts_where', 11, 2 );
function titol_posts_where( $where, &$wp_query )
{
  global $wpdb;
 global $wp;
  if ($_GET['search-type'] == 'general') {
    $where .= ' OR ' . $wpdb->posts . '.post_title LIKE \'' . esc_sql(   $wpdb->esc_like( $_GET['s'] ) ) . '%\'';
 str_replace("LIKE", "", $where);
  }
  return $where;
 }

Hope this can be helpful to somebody and thanks again to @tomjnewell , @Joel and @user5200704

0

The parameter for meta query is meta_key, not just key (according to https://codex.wordpress.org/Class_Reference/WP_Query)

Try 'meta_key' => 'autor' instead of 'key' => 'autor'

1
  • Thanks for answer, Joel, but is no working Apr 17, 2016 at 22:18

Your Answer

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

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