Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

I got strange problem and im stuck. I have custom post type with around 15 custom fields.

I moved data from old db (not wp) by using wp_insert_post ,update_post_meta and wp_set_object_terms.

All went good. All vcards works fine. I got 3500 vcards and now when i try to search some vcards - search just freeze for 10 minutes then i get timeout. Same thing is in admin panel if i try to search in custom post type menu search takes 10 minutes and dies... So i have a question is wordpress capable to handle that amount of custom post type posts ? or i made some mistake in coding ? If You need any kind of code to show please tell me i will paste it here since now i dont even know where to start search.

Best Regards Charles


Here is a code:

First of all i drop other pages from search - i need only my custom post type

function search_types($query) {
if ( $query->is_search ) 
{
    $query->set('post_type', 'vcard');

}
return $query;

This part of code i found on net and just adjusted it to my needs: I grab all custom fields ( now in code i got only 1 field becouse of testing - normally is about 15)

function custom_fields_search() {
global $wpdb;

$sql = "SELECT meta_key FROM ". $wpdb->prefix . "postmeta mk WHERE mk.meta_key LIKE 'companyKeyWords'";
$results = $wpdb->get_results( $sql );

if ( $results ) :
    foreach ($results as $result) {
        $custom_fields[] = $result->meta_key;
    }
endif;

return $custom_fields;

Now those 3 function with filter

function custom_search_groupby($groupby) {
global $wpdb, $wp_query;

$groupby = "$wpdb->posts.ID";

return $groupby;
function custom_search_join($join) {
global $wpdb, $wp_query;

if ( is_search() && isset($_GET['s']) ) {

    $join  = " INNER JOIN $wpdb->term_relationships AS r ON ($wpdb->posts.ID = r.object_id) ";
    $join .= " INNER JOIN $wpdb->term_taxonomy AS x ON (r.term_taxonomy_id = x.term_taxonomy_id) ";
    $join .= " AND x.taxonomy = '".GO_TAX_CAT."'";


    // if an ad category is selected, limit results to that cat only
    $catid = $wp_query->query_vars['cat'];

    if ( !empty($catid) ) :

        // put the catid into an array
        (array) $include_cats[] = $catid;

        // get all sub cats of catid and put them into the array
        $descendants = get_term_children( (int) $catid, GO_TAX_CAT );

        foreach ( $descendants as $key => $value )
            $include_cats[] = $value;

        // take catids out of the array and separate with commas
        $include_cats = "'" . implode( "', '", $include_cats ) . "'";

        // add the category filter to show anything within this cat or it's children
        $join .= " AND x.term_id IN ($include_cats) ";

    endif; // end category filter


    $join .= " INNER JOIN $wpdb->postmeta AS m ON ($wpdb->posts.ID = m.post_id) ";
    $join .= " INNER JOIN $wpdb->terms AS t ON x.term_id = t.term_id ";

}

return $join;

}

function custom_search_where($where) {
global $wpdb, $wp_query;
$old_where = $where; // intercept the old where statement
if ( is_search() && isset($_GET['s']) ) {

    // get the custom fields to add to search
    $custom_fields = custom_fields_search();
    $customs = $custom_fields;

    $query = '';

    $var_q = stripslashes($_GET['s']);
    //empty the s parameter if set to default search text
    if ( __('What are you looking for?','go') == $var_q ) {
        $var_q = '';
    }

    if ( isset($_GET['sentence']) || $var_q == '' ) {
        $search_terms = array($var_q);
    }
    else {
        preg_match_all('/".*?("|$)|((?<=[\\s",+])|^)[^\\s",+]+/', $var_q, $matches);
        $search_terms = array_map(create_function('$a', 'return trim($a, "\\"\'\\n\\r ");'), $matches[0]);
    }

    if (!isset($_GET['exact']) ) $_GET['exact'] = '';

    $n = ( $_GET['exact'] ) ? '' : '%';

    $searchand = '';

    foreach ( (array)$search_terms as $term ) {
        $term = addslashes_gpc($term);

        $query .= "{$searchand}(";
        $query .= "($wpdb->posts.post_title LIKE '{$n}{$term}{$n}')";
        $query .= " OR ($wpdb->posts.post_content LIKE '{$n}{$term}{$n}')";
        $query .= " OR ((t.name LIKE '{$n}{$term}{$n}')) OR ((t.slug LIKE '{$n}{$term}{$n}'))";

        foreach ( $customs as $custom ) {
            $query .= " OR (";
            $query .= "(m.meta_key = '$custom')";
            $query .= " AND (m.meta_value  LIKE '{$n}{$term}{$n}')";
            $query .= ")";
        }

        $query .= ")";
        $searchand = ' AND ';
    }

    $term = $wpdb->escape($var_q);

    if ( !isset($_GET['sentence']) && count($search_terms) > 1 && $search_terms[0] != $var_q ) {
        $query .= " OR ($wpdb->posts.post_title LIKE '{$n}{$term}{$n}')";
        $query .= " OR ($wpdb->posts.post_content LIKE '{$n}{$term}{$n}')";
    }

    if ( !empty($query) ) {

        $where = " AND ({$query}) AND ($wpdb->posts.post_status = 'publish') ";

        // setup the array for post types
        $post_type_array = array();

        // always include the ads post type
        $post_type_array[] = GO_POST_TYPE;


        // build the post type filter sql from the array values
        $post_type_filter = "'" . implode("','",$post_type_array). "'";

        // return the post type sql to complete the where clause
        $where .= " AND ($wpdb->posts.post_type IN ($post_type_filter)) ";

    }
}

return( $where );

At the end, I applyfilters :

add_filter('posts_join', 'custom_search_join');
add_filter('posts_where', 'custom_search_where');
add_filter('posts_groupby', 'custom_search_groupby');
share|improve this question
1  
How are you performing the search? get_posts? Or something else? For large sets of data, I'd generally go for custom queries (with pre-populated IN clauses, esp. in older versions of MySQL); so yes, please, show us some code. –  soulseekah Mar 10 '12 at 17:01
    
I use custom query with posts_join posts_where posts_groupby filter. –  Charles Kłyciński Mar 10 '12 at 17:25
    
@Charles Sidenote: You could also use the posts_clauses filter instead of 3 single filter - only a question of how you want to do it, as it doesn't change anything. –  kaiser Mar 10 '12 at 18:07
    
If you can guide me a little for best solution to make that search. I got 1 input field in search form. Search should look for entered work in all custom fields. That is in short what i need –  Charles Kłyciński Mar 10 '12 at 18:30

1 Answer 1

up vote 2 down vote accepted

You got a preg_match_all(), various JOINs, anonymous/lambda functions. In short: Everything that makes debugging hard and is performance wise a no-go.

In short: You should use a meta_query instead. Take a look at

Code meta_query » Multiple Custom Field Handling:

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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