0

I have a search query that is running on through a custom post type, but its search for all parts of text, not full sentences.

E.g. if you search for Menta as a company name, it will also display an entry with Complementary in the text content.

I need to find a way to amend this function below to either only search the post title and nothing else, which would be the ideal solution. Or if thats not possible, then to only search for full words not parts. I hope that makes sense.

This is the code:

    function aitIncludeMetaInSearch($where) {
        remove_filter('posts_where', 'aitIncludeMetaInSearch');

        global $wpdb;
        // this filter callbeck can be used in ajax requests
        // search string doesn't exist in ajax requests
        // therefore search keyword must be passed as a global query from other scope
        global $__ait_query_data;
        $searchKeyword = $__ait_query_data['search-params']['s'];

        // list of meta keys where we are searching
        $metaKeys = array('subtitle', 'features_search_string');
        $metaKeys = "'" . implode( "', '", esc_sql( $metaKeys ) ) . "'";

        $toFind = "(".$wpdb->posts . ".post_title";

        $likeClause = $wpdb->esc_like( $searchKeyword );
        $likeClause = '%' . $likeClause . '%';

        // search in postmeta values and return array of post ids
        $subQuery = $wpdb->prepare(
            "SELECT group_concat(post_id) as ids FROM {$wpdb->postmeta} AS postmeta
                WHERE postmeta.meta_value LIKE %s
                AND postmeta.meta_key IN ({$metaKeys})",
            $likeClause
        );
        $subQuery = "(FIND_IN_SET(".$wpdb->posts.".ID, (".$subQuery."))) OR ";

        $subqueryLength = strlen($subQuery);

        $positions = aitFindStrPos($toFind, $where);

        $newWhere = $where;
        for ($i = 0; $i < sizeof($positions); $i++) {
            // insert subquery on each position where $toFind occured
            // consider that each next position is moved by the length of previously inserted subquery
            $newWhere = substr_replace($newWhere, $subQuery, $positions[$i] + $i * $subqueryLength, 0);
        }

        // Return revised WHERE clause
        return $newWhere;
    }

Any help would be great :D

benlumley
  • 11,370
  • 2
  • 40
  • 39

1 Answers1

0

This function looks like it aims to add in meta searching, not to restrict the existing search to the post title only. If you want to do that, try removing the code you have and using the code here:

Make wordpress search only in post title

The full word vs partial match can't be done with a LIKE query, but can be done with regex

See: Search for "whole word match" in MySQL

function aitIncludeMetaInSearch($where) {
    remove_filter('posts_where', 'aitIncludeMetaInSearch');

    global $wpdb;
    // this filter callbeck can be used in ajax requests
    // search string doesn't exist in ajax requests
    // therefore search keyword must be passed as a global query from other scope
    global $__ait_query_data;
    $searchKeyword = $__ait_query_data['search-params']['s'];

    // list of meta keys where we are searching
    $metaKeys = array('subtitle', 'features_search_string');
    $metaKeys = "'" . implode( "', '", esc_sql( $metaKeys ) ) . "'";

    $toFind = "(".$wpdb->posts . ".post_title";

    $likeClause = $wpdb->esc_like( $searchKeyword );
    $regexClause = '[[:<:]]' . $likeClause . '[[:>:]]';

    // search in postmeta values and return array of post ids
    $subQuery = $wpdb->prepare(
        "SELECT group_concat(post_id) as ids FROM {$wpdb->postmeta} AS postmeta
            WHERE postmeta.meta_value REGEXP %s
            AND postmeta.meta_key IN ({$metaKeys})",
        $regexClause
    );
    $subQuery = "(FIND_IN_SET(".$wpdb->posts.".ID, (".$subQuery."))) OR ";

    $subqueryLength = strlen($subQuery);

    $positions = aitFindStrPos($toFind, $where);

    $newWhere = $where;
    for ($i = 0; $i < sizeof($positions); $i++) {
        // insert subquery on each position where $toFind occured
        // consider that each next position is moved by the length of previously inserted subquery
        $newWhere = substr_replace($newWhere, $subQuery, $positions[$i] + $i * $subqueryLength, 0);
    }

    // Return revised WHERE clause
    return $newWhere;
}
benlumley
  • 11,370
  • 2
  • 40
  • 39