Categories
How To

Optimizing Post Meta Search

Trimming down the meta key names I searching for to prioritize my results in a WordPress search.

While I’m currently using Adam Balee’s technique to add more custom meta to my search results, it had one flaw to me.

See, his search added all the post meta, and really I didn’t want that. While I’m still deep in the woods of getting ElasticSearch to prioritize for me, what I needed was for the search to only look at specific post_meta fields. And for that, I needed to change the search query just a little bit.

The original code has a section where it updates the Where clause:

	$where = preg_replace(
		"/\(\s*".$wpdb->posts.".post_title\s+LIKE\s*(\'[^\']+\')\s*\)/",
		"(".$wpdb->posts.".post_title LIKE $1) OR (".$wpdb->postmeta.".meta_value LIKE $1)", $where );

Now originally I thought I could just add on to that, but for just changing it to this didn’t work:

	$where .= OR (".$wpdb->postmeta.".meta_value LIKE $1);

That’s because there’s no way to know what $1 is. I tried this as well but it didn’t work:

	$where .= " OR ( ".$wpdb->postmeta.".meta_value LIKE '%".$wp->query_vars['s']."%' )";

So accepting I would have to keep using preg_replace I thought about what I was searching and what I wanted. I didn’t want the search to show every character with the tag ‘homosexual’ for example, because that was a custom taxonomy and people can look for that if they wanted to see all the homosexuals. That meant I trimmed down the list of meta fields I needed to search.

My final result was this: chars_actor, shows_worthit_details, shows_plots, shows_episodes, shows_realness_details, shows_quality_details, and shows_screentime_details.

I left out the metas for ratings, because all that would do is mean if you search for a ‘5’ for example, you’d get all the things rated five without enough context. (That reminds me I need to code in a way to sort shows by rankings…).

Anyway, my code looks like this:

	$keys = "'chars_actor', 'shows_worthit_details', 'shows_plots', 'shows_episodes', 'shows_realness_details', 'shows_quality_details', 'shows_screentime_details'";

        $where = preg_replace(
            "/\(\s*".$wpdb->posts.".post_title\s+LIKE\s*(\'[^\']+\')\s*\)/",
            "(".$wpdb->posts.".post_title LIKE $1) OR ( (".$wpdb->postmeta.".meta_key IN ( ".$keys." ) ) AND (".$wpdb->postmeta.".meta_value LIKE $1)  )", $where );

That change is in the OR clause, where it says “OR if the post meta key name is in my list of keys, AND has a value like my search, then add to the results.”

I feel it’s a little clunky, but it works.