WooCommerce popularity and price sorting

Many WooCommerce users use search sorting that allows users to sort by popularity or price. Unfortunately while Relevanssi works fine with WooCommerce, those sorts do not work. Relevanssi doesn’t know about price or popularity, and the sorting assumes there’s default WP search underneath. Relevanssi doesn’t do meta field sorting as easily as the default WP search does.

No worries, though. All you need to do is to tell Relevanssi how to sort those posts. First, however, you need to disable the meta key parameter, because that messes things up with Relevanssi:

add_filter('relevanssi_modify_wp_query', 'rlv_remove_price');
function rlv_remove_price($query) {
    if (isset($query->query_vars['meta_key']) && $query->query_vars['meta_key'] == "_price") {
        $query->query_vars['meta_key'] = "";
        global $price_sort;
        $price_sort = strtolower($query->query_vars['order']);
    }
    if (isset($query->query_vars['meta_key']) && $query->query_vars['meta_key'] == "total_sales") {
        $query->query_vars['meta_key'] = "";
        global $sales_sort;
        $sales_sort = true;
    }
    return $query;
}

This function checks if the meta_key is set to _price or total_sales (if the meta field names are different in your installation, you need to change them here) and clears out the meta_key field while setting a global variable that can be accessed later on.

add_filter('relevanssi_hits_filter', 'rlv_price_sort');
function rlv_price_sort($hits) {
    global $wp_query, $price_sort, $sales_sort;
 
	if (isset($price_sort)) {
		$prices = array();
	    	foreach ($hits[0] as $hit) {
        		$price = get_post_meta($hit->ID, '_price', true);
	       		if (!isset($prices[$price])) $prices[$price] = array();
			array_push($prices[$price], $hit);
	       	}
 
		if ($price_sort == 'asc') {
			ksort($prices);
		} else {
			krsort($prices);
		}
 
	   	$sorted_hits = array();
		foreach ($prices as $price => $year_hits) {
   	   		$sorted_hits = array_merge($sorted_hits, $year_hits);
	    	}
		$hits[0] = $sorted_hits;
	}
 
	if (isset($sales_sort)) {
		$sales = array();
	    	foreach ($hits[0] as $hit) {
        		$sale_count = get_post_meta($hit->ID, 'total_sales', true);
	       		if (!isset($sales[$sale_count])) $sales[$sale_count] = array();
			array_push($sales[$sale_count], $hit);
	       	}
 
		krsort($sales);
 
	   	$sorted_hits = array();
		foreach ($sales as $sale_count => $year_hits) {
   	   		$sorted_hits = array_merge($sorted_hits, $year_hits);
	    	}
		$hits[0] = $sorted_hits;
	}
 
    return $hits;
}

This second function does the actual sorting. Again, it assumes the price is in _price custom field and that the popularity is based on total_sales.

  • SM

    hi, where does this code get added?

    thanks!