Posted on

Custom weighing with relevanssi_match and relevanssi_results

The relevanssi_match hook lets you modify the matches found for queries. It passes a match object, which has the post id ($match->doc), number of hits found in different parts of the post and the weight assigned to the post ($match->weight).

Here’s how Relevanssi calculates the weight:

$match->tf =
    $match->title * $title_boost +
    $match->content +
    $match->comment * $comment_boost +
    $match->tag * $tag_boost +
    $match->link * $link_boost +
    $match->author +
    $match->category +
    $match->excerpt +
    $match->taxonomy +
    $match->customfield;

$match->weight = $match->tf * $idf;

Where $idf is the inverse document frequency, aka the rarity of the term in question. The bigger the weight, the higher the document will appear on the search results list. Weights are calculated for each term in the search query and multiplied to get the final weight for the document.

So, now, if you want to say adjust the weights by freshness, you could fetch the post date based on post_id and multiply the $match->weight with some boost factor if the publication date falls within some range (say within the last week) and with another boost factor if it falls outside that range. Want to boost the weight if a specific custom field is present? Easy!

This filter will give you lots of tools to adjust and fine-tune the weights assigned to documents.

Weighing terms vs posts

If your weights are based on posts and not terms, you can also use the relevanssi_results filter hook. This filter hook gives you an array of (post ID, weight) pairs, and it’s a good option for adjusting result weights based on the post.

The following examples will use both filters as necessary.

Performance problems possible

Note that many of these methods can cause lots of database queries and thus performance problems. These functions are simple examples and springboards for better solutions. There are some tips for improving the performance at the end of the page.

How to use these functions?

If you don’t know how to use these functions, please read Adding custom functions to your site.

Table of contents

Date-based weight

Here’s an example function that will double the weight of posts published within one week and halve the weight of posts older than that.

add_filter( 'relevanssi_match', 'date_weights' );
function date_weights( $match ) {
	$post_date = get_the_time( 'U', $match->doc );
	if ( time() - $post_date < WEEK_IN_SECONDS ) {
 		$match->weight = $match->weight * 2;
	} else {
		$match->weight = $match->weight / 2;
	}
	return $match;
}

// Or use this, but definitely not both
add_filter( 'relevanssi_results', 'date_weights' );
function date_weights( $results ) {
	array_walk(
        $results,
        function( &$weight, $post_id ) {
            $post_date = get_the_time( 'U', $post_id );
	        if ( time() - $post_date < WEEK_IN_SECONDS ) {
 		        $weight = $weight * 2;
            } else {
                $weight = $weight / 2;
            }
        }
    );
    return $results;
}

If you want more dynamic date-based weighting, this function counts the date difference between now and the post publication. It converts that to a multiplier with the formula 500 / difference in days, leading to a massive boost for new posts:

add_filter( 'relevanssi_results', 'rlv_dynamic_time_weights' );
function rlv_dynamic_time_weights( $results ) {
    array_walk(
        $results,
        function( &$weight, $post_id ) {
            $now       = date_create( 'now' );
            $post_date = date_create( get_the_time( 'Y-m-d', $post_id ) );
            $diff_days = $now->diff( $post_date, true )->format( '%a' );

            if ( $diff_days < 1 ) {
                $diff_days = 1;
            }

            $multiplier = 500 / $diff_days;
            $weight     = $weight * $multiplier;
        }
    );

	return $results;
}

Custom field -based weight

This function will double the weight of posts with the custom field “featured” set to 1.

add_filter( 'relevanssi_match', 'custom_field_weights' );
function custom_field_weights( $match ) {
	$featured = get_post_meta( $match->doc, 'featured', true );
	if ( '1' === $featured ) {
 		$match->weight = $match->weight * 2;
	} else {
		$match->weight = $match->weight / 2;
	}
	return $match;
}

This function will increase the weight if the search term matches any custom field:

add_filter( 'relevanssi_match', 'rlv_customfield_boost' );
function rlv_customfield_boost( $match ) {
	if ( $match->customfield > 0 ) {
		$match->weight *= 10;
	}
	return $match;
}

With Relevanssi Premium, you also have the customfield_detail field, which allows you to filter results by custom field. If you want a search that only targets one specific custom field, you can do a filter like this, where field_name is the name of the field.

add_filter( 'relevanssi_match', 'custom_field_weights' );
function custom_field_weights( $match ) {
	$custom_field_detail = json_decode( $match->customfield_detail );
	if ( null === $custom_field_detail || ! isset( $custom_field_detail->field_name ) ) {
		$match->weight = 0;
	}
	return $match;
}

This function sets the weight of the match to 0 if Relevanssi doesn’t find the match in a custom field value or finds it in the wrong custom field. For a positive boost for matches in a particular custom field (in this example field_name):

add_filter( 'relevanssi_match', 'custom_field_weights' );
function custom_field_weights( $match ) {
	$custom_field_detail = json_decode( $match->customfield_detail );
	if ( null !== $custom_field_detail && isset( $custom_field_detail->field_name ) ) {
		$match->weight *= 2;
	}
	return $match;
}

Adding extra weight to users

Relevanssi Premium doesn’t have an easy setting to increase the weight of users in the results. This function will double the weight of user profiles:

add_filter( 'relevanssi_results', 'rlv_user_weights' );
function rlv_user_weights( $results ) {
    array_walk(
        $results,
        function( &$weight, $post_id ) {
            if ( 'user' === relevanssi_get_post_type( $post_id ) ) {
                $weight *= 2;
            }
        }
    );

	return $results;
}

Weight from taxonomy terms

Here’s how you can add extra weight to posts that have a particular taxonomy term. Just add this function and replace term with the slug of the term and taxonomy with the slug of the taxonomy (for example category or post_tag).

add_filter( 'relevanssi_match', 'rlv_boost_one_term' );
function rlv_boost_one_term( $match ) {
	if ( has_term( 'term', 'taxonomy', $match->doc ) ) {
		$match->weight *= 5;
	}
	return $match;
}

has_term() also works without the first parameter, in which case it will boost the weight if any term from the taxonomy is present (even if the term doesn’t match the search query).

add_filter( 'relevanssi_match', 'rlv_boost_all_terms' );
function rlv_boost_all_terms( $match ) {
	if ( has_term( '', 'taxonomy', $match->doc ) ) {
		$match->weight *= 5;
	}
	return $match;
}

Weight from tags

Relevanssi Premium has a simple weight setting for adding weight to tags. If you want that in free Relevanssi, you have to use relevanssi_match to add extra weight to tags.

add_filter( 'relevanssi_match', 'rlv_tag_boost' );
function rlv_boost_tags( $match ) {
	if ( $match->tag > 0 ) {
		$match->weight = $match->weight * 5 * $match->tag;
	}
	return $match;
}

Weight from excerpts

To add more weight to hits from excerpts, you can do something like this:

add_filter( 'relevanssi_match', 'rlv_boost_excerpts' );
function rlv_boost_excerpts( $match ) {
	if ( $match->excerpt > 0 ) {
		$match->weight *= 2;
	}
	return $match;
}

This function will make any hits that match the excerpt more significant.

Weighing multisite subsites

If you want to give extra weight to results from a particular subsite in multisite searches, you can do this:

add_filter( 'relevanssi_match', 'rlv_boost_subsite' );
function rlv_boost_subsite( $match ) {
	if ( 3 === get_current_blog_id() ) {
		$match->weight *= 10;
	}
	return $match;
}

This function will give a boost to all results from blog 3.

More weight for whole word matches

When doing partial matching, this function gives a heavy boost for posts that have a whole word match:

add_filter( 'relevanssi_match', 'rlv_prefer_whole_words', 10, 3 );
function rlv_prefer_whole_words( $match, $idf, $term ) {
    if ( $match->term === $term ) {
        $match->weight *= 1000;
    }
    return $match;
}

Return only comments

If you want to create a search form that only searches within comments, you can do it with relevanssi_match. You need to add a parameter to the search form that indicates to Relevanssi that the search should only target comments. You can do it like this:

[searchform comments="1"]

This function creates a search form with the comments parameter set to “1”. Now we can check for that in our relevanssi_match filter:

add_filter( 'relevanssi_match', 'rlv_comments_only' );
function rlv_comments_only( $match ) {
    if ( $_REQUEST['comments'] ) {
        if ( $match->comment < 1 ) {
            $match->weight = 0;
        }
    }
    return $match;
}

If the comments parameter is “1”, the filter will exclude all matches that don’t match to comment content.

Weight based on parent

Here’s how to adjust weight based on the parent page:

add_filter( 'relevanssi_results', 'rlv_parent_weights' );
function rlv_parent_weights( $results ) {
    array_walk(
        $results,
        function( &$weight, $post_id ) {
            if ( in_array( wp_get_post_parent_id( $post_id ), array( 1, 2, 3 ), true ) ) {
                $weight *= 0.5;
            }
        }
    );

	return $results;
}

This function will reduce the weight of all pages under pages 1, 2 and 3 by half.

This function will increase the weight of all parent pages:

add_filter( 'relevanssi_results', function ( $results ) {
    global $wpdb;
    $child_posts = $wpdb->get_col( "SELECT ID FROM $wpdb->posts WHERE post_parent > 0 AND ID IN (" . implode( ',', array_keys( $results ) ) . ")" );
    $child_posts = array_flip( $child_posts );

    array_walk(
        $results,
        function( &$weight, $post_id ) use ( $child_posts ) {
            if ( ! isset( $child_posts[ $post_id ] ) ) {
                // Not a child post.
                $weight *= 10;
            }
        }
    );
	return $results;
} );

This function will add extra weight to posts with featured images:

add_filter( 'relevanssi_results', 'rlv_featured_post_boost' );
function rlv_featured_post_boost( $results ) {
    array_walk(
        $results,
        function( &$weight, $post_id ) {
            if ( has_post_thumbnail( $post_id ) ) {
                $weight *= 5;
            }
        }
    );
	return $results;
}

Boost matches for title beginning

If you want to boost matches where the search term appears at the beginning of the post title, you can use this snippet:

add_filter( 'relevanssi_match', 'rlv_title_beginning', 10, 3 );
function rlv_title_beginning( $match, $idf, $term ) {
    $title = get_the_title( $match->doc );
    if ( strtolower( relevanssi_substr( $title, 0, relevanssi_strlen( $term ) ) ) === $term ) {
        $match->weight *= 1000;
    }
    return $match;
}

Performance issues

Notice that many of these methods come with a performance hit. It’s worth noting that a filter like this may cause hundreds, if not thousands, of extra database queries when searching, and that may cause a significant slowdown in the search performance.

The first step is to be aware of the situation. Install Query Monitor: it will show you the number of database queries performed when loading the page. Run a search with and without the filter and see how the number of database queries changes. If you see the number of queries grow a lot, you may have a problem.

Often you can fix these things with a bit of clever programming. A typical scenario is to check for a taxonomy term with has_term(). Every has_term() is at least one database query. If you have lots of posts, this may easily mean 1,000 database queries!

Here’s a way to replace those database queries with just one database query. Instead of has_term(), use this function:

/**
 * Checks whether a post has a term.
 *
 * Functions the same as has_term(), but does only one database query
 * per taxonomy, no matter how many posts are checked. The taxonomy
 * relationships between posts and terms are fetched once, and future
 * requests check the table that is kept in memory.
 *
 * @param string $term     The term slug.
 * @param string $taxonomy The taxonomy name.
 * @param int    $post_id  The post ID.
 *
 * @return boolean True, if the post has the term, otherwise false.
 */
function rlv_has_term( $term, $taxonomy, $post_id ) {
    global $wpdb, $relevanssi_taxonomy_cache;
    if ( isset( $relevanssi_taxonomy_cache[ $taxonomy ] ) ) {
        return isset( $relevanssi_taxonomy_cache[ $taxonomy ][ $term ][ $post_id ] );
    }
    $taxonomy_array = $wpdb->get_results(
        "SELECT t.slug, object_id FROM $wpdb->term_relationships AS tr,
            $wpdb->term_taxonomy AS tt, $wpdb->terms AS t
        WHERE tr.term_taxonomy_id = tt.term_taxonomy_id
            AND tt.taxonomy = '$taxonomy' AND t.term_id = tt.term_id" );
    foreach ( $taxonomy_array as $term_object ) {
        $relevanssi_taxonomy_cache[ $taxonomy ][ $term_object->slug ][ $term_object->object_id ] = true;
    }
    return isset( $relevanssi_taxonomy_cache[ $taxonomy ][ $term ][ $post_id ] );
}

Using this function will run only one database query per taxonomy because it fetches all post-term relationships for the taxonomy at once, keeps them in memory and fetches future requests from that cache.

You can create similar caching solutions for other problematic functions as well. All it takes is figuring out a problem and then coming up with a method to reduce the number of queries.

64 comments Custom weighing with relevanssi_match and relevanssi_results

  1. Very interesting feature. I have to take a look on this and try to make it works (I suppose the function is to be put in functions.php).

  2. Would you be so nice and post a simple help how to boost search results by custom_field for exampele custom_field called “featured”. I have some posts with customfield “featured” value “1” and other with no customfield. I’ve bought your premium edition of relevanssi but I don’t know how to make it work. THANKS !!!

  3. Hi Mikko,
    I want to use relevanssi with wp-ecommerce. I know that wp-ecommerce uses custom post types and tags. Relevanssi ‘out of the box’ does not (obviously) work with wp-commerce. I was wondering if there is something or somewhere in the code that could be changed so relevanssi can use wp-ecommerce product tags and titles.

  4. Can you add a multiplier to something like the custom field? aka:
    *****
    add_filter(‘relevanssi_match’, ‘add_weight_to_cf’);
    function add_weight_to_cf($match) {
    $match->customfield = $match->customfield * 2;
    return $match;
    }
    *****

    I’m not sure if the $match->weight is calculated dynamically or not. If this isn’t possible, it is possible to add a weight to a custom field with this hook or another?

    1. $match->weight is calculated before the filter, so you’d need to recalculate it, if you want to something like that. However, now that I look at it, that’s going to be tricky, because calculating the weight (tf * idf) needs the idf component as well, and that’s a bit tricky to get. I’ll add this to my to-do list for the next version, to have the idf passed to the filter as well.

      Actually, you can do it like this. $match->weight is tf * idf. Well, tf is

      $match->tf =
      $match->title * $title_boost +
      $match->content +
      $match->comment * $comment_boost +
      $match->link * $link_boost +
      $match->author +
      $match->excerpt +
      $match->taxonomy_score +
      $match->customfield +
      $match->mysqlcolumn;

      Calculate that, then you can divide the weight with that to get the idf. Then just calculate a new tf with the modifiers you want and multiply it with the idf to get new value for $match->weight.

      But yeah, I’ll make this easier in the next version. There are reasons why the weight is calculated before the filter (some filters may want to adjust the weight directly).

      1. Mikko, Got it. That solution will work great for now.

        As an aside, it would be nice to be able to also weight each custom field separately. But, I am probably one of the few who really wants to do that.

        Thanks again.

        1. That information is stored — the Relevanssi MySQL database has a column “customfield_detail”, which tells which custom fields have the hit. You’ll have to dig that up yourself, but the information is there and you can use it.

        2. I would love to be able to set individual weights on my custom fields too. If you add that, I’ll be a premium customer for sure!

          1. That is possible in Premium. There’s no ready option for it, so you have to create a filter function that adjusts the weights, but I can write a knowledge base article about how to do that. It’s not particularly complicated.

          2. I grabbed the sample code from the knowledge base and adapted it a little. I’m wondering if there’s a better way to to what I’ve done below. Basically custom fields are almost exclusively what’s important to me in my posts, so I want them to have all have a higher weight.

            add_filter(‘relevanssi_match’, ‘custom_field_weights’);

            function custom_field_weights($match) {

            $fields=array(‘Cust Field 1′,’ Cust Field 1 ,’Cust Field 1′,’Cust Field 1′,’Cust Field 1′,’Cust Field 1′);

            foreach ($fields as $field) {
            $custom_field = get_post_meta($match->doc, $field, true);
            if (‘1’ == $custom_field) {
            $match->weight = $match->weight * 2;
            }
            else {
            $match->weight = $match->weight / 2;
            }
            }
            return $match;
            }

            Is there a better way to do what I’m doing above? I’ve been reviewing the Premium features. I probably will go ahead either way and get premium.

          3. That’s how you do it. Relevanssi Premium provides you with an array of custom fields that match the search query, but if you don’t care about that and only care about whether the custom field is present or has some fixed value, then you won’t need that.

          4. I don’t need to worry about whether or not the custom field exists, I know they exist. I’m looking for posts that have matches for the search terms in the custom fields.

            You could take a look at my site http://www.aviationphotographic.com users might search for something like “qantas boeing 747 lax”. When you do that search, 1 result is returned. However I know there’s a couple more than that. I’m not sure why the others don’t show up.

            My results are pretty mixed. Something they come back really relevant, and other times not so much. I use “AND – require all items” as my default operator for search, and I disabled “OR fallback”. I do allow fuzzy results if there’s no hits.

          5. Ok, in that case you can do it with some modifications to the code you posted, or easier with Relevanssi Premium.

            As for why you’re not fing all Qantas Boeing 747 LAX photos, are you using the limit searches feature? If you are, try disabling that feature and see if that helps. I made some searches, and you should definitely find at least two photos with that search phrase.

          6. I disabled the “limit searches” feature, and it did improve the results (i did notice that the option kept re-enabling it’s self until I did a full re-index). It got a bit slower too, but I expected that. In terms of performance, is there an easy way to integrate relevanssi to use memcache? That would be an awesome option, and I think it would improve performance a fair amount.

          7. Hmm, I’ll have to check the option. It shouldn’t re-enable itself.

            Re: memcache, I have to admit I have no idea what that would require and if it is a good idea.

    2. Hi Mikko

      Is there a way to add most weight to fetch matching page titles (not post titles) first?

      Would really appreciate if you could show how this can be done?

      Thanks
      Arjun

        1. Hi Mikko

          Thanks for pointing me in the right direction. That really helped. I can now pull pages before posts. I have also put in code for extra boost for exact title matches. That is working well too. I had a follow up question.
          Is there a way to fetch pages where the search term appears in the content of the page but is not part of the title. For example – I search “Nike”, and I know Nike related posts appears on my “Clothing & Fashion” page. Can the search results first fetch the Clothing & Fashion page and then show all other results with Nike?

          Would really appreciate if you could point me in the right direction with this.

          Thanks & Regards
          Arjun

          1. Arjun, the easiest solution here is to decrease the weight of the titles or increase the weight of the post content, until you get the posts in the desired order.

  5. I’ve got my version of your function working, but need a clarification.

    I have checkboxes representing my Custom Fields. The function reads my checkboxes from my Advanced Search Form, and eliminates posts containing the search term only in unchecked Custom Fields. So it appears to the user as if he’s searching only within his chosen Custom Fields. Something like that.

    The question is that I cannot get results which occur in the title to move to the bottom. I set the title weight to 4 in Admin Settings, but I think my function is making it 5 again. I’m not even certain that matches in the Title should move to the bottom of the results (thinking about it), but anyway here’s the code in case someone needs it:

    add_filter('relevanssi_match', 'cfdetail');
    function cfdetail($match) {
    	//html sample 
     
    	$checked_fields = $_GET['checkers'];  
     
    	$checkboxes = array(
    	0=&gt; "meta_results", 
    	1=&gt; "meta_inputs", 
    	2=&gt; "meta_purpose", 
    	3=&gt; "meta_special", 
    	4=&gt; "meta_references",  
    	);
     
    	$cf = unserialize($match-&gt;customfield_detail);
     
    	if ($cf &amp;&amp; $checked_fields) {
    		//do subtraction here, in case they unchecked all the boxes, prevent an error message.
    		$unchecked_fields = array_diff($checkboxes, $checked_fields);
     
      		foreach ($unchecked_fields as $u) {
    			if (!in_array( $u, array_keys($cf)) ) {
          			$match-&gt;weight = 5;
      	    		}
            		else {
            			$match-&gt;weight = 0;
            		}
    		}
    	// 'else' statement is not required because the function will return unfiltered results if they unchecked all boxes.
    	}
    	return $match;    
    }

    PS – If anyone else is as clueless as me, you may also want to know that you create the Advanced Search Form by adding comment to top of your own PHP, & then using it as “template” for a page design in the Admin. Or at least, that worked, I don’t know if it’s the best way.
    /**
    * Template Name: Advanced Search
    */

    1. You should probably adjust the weights to make the differences more pronounced. Difference between weight 5 and weight 4 is very small, much smaller than differences between the weights of the terms themselves. Make it 10 and 2, and you’ll see more of a difference.

  6. Here’s how I got Relevanssi Premium to assign different weights to results based on their categories, if it’s helpful for anyone else:

    Simply change the value of $category_id to the category you want to affect, then change the value of $match->weight to whatever you want the weighting to be (eg: ‘$match->weight * 5’ will multiply the weight of that category by five, ‘$match->weight /5’ will divide the weight by five, etc). Place this code within your functions.php and it should work…
    Thanks for the help Mikko!

    add_filter(‘relevanssi_match’, ‘category_weight’);
    function category_weight($match) {
    $category = get_the_category($match->doc);
    $category_id = $category[0]->cat_ID;
    if ($category_id == ’22’){
    $match->weight = $match->weight / 10;
    }
    elseif ($category_id == ‘3’) {
    $match->weight = $match->weight * 1;
    }
    elseif ($category_id == ‘4’) {
    $match->weight = $match->weight * 4;
    }
    else {
    }
    return $match;
    }

    1. Yes, but it requires some programming. Filter ‘relevanssi_match’ lets you modify weights. The $match->customfield_detail shows where the custom field hit was made. See the example code in Dan’s comment.

  7. Ahh – additional info: You probably need to know that that field is also on a custom post type called products 😉

  8. Hi Mikko,

    I would like to use this function to make pages with a specific -tag- appear at the top of the results. I’m trying the following:

    add_filter(‘relevanssi_match’, ‘custom_tag_weights’);
    function custom_tag_weights($match) {
    $global_option = has_tag(‘global_option’, $match->doc);
    if ( $global_option ) {
    $match->weight = $match->weight * 1000;
    }
    else {
    $match->weight = $match->weight / 2;
    }
    return $match;
    }

    …this -seems- to work, but it never brings the results to the -top-. Page Title always seems to be weighted higher. In my Indexing Options, I have Title weighted as ’10’. How can I adjust this?

  9. I want to change the taxonomy weight. In backend I can change the weights for post_tags and categories but not for taxonomies.

    I tried it that way without success:

    add_filter(‘relevanssi_match’, ‘custom_tax_weights’);

    function custom_tax_weights($match) {
    $match->taxonomy = $match->taxonomy * 50;
    return $match;
    }

    1. Sebastian, that’s not doing anything. Relevanssi sorts by $match->weight, and unless you change that, you’re not going see any results. Take a look at lib/search.php and see how Relevanssi calculates $match->tf. Copy that to your function, with the added weight to $match->taxonomy_score, recalculate $match->weight from $match->tf and $idf ($idf comes as a parameter for relevanssi_match filter).

  10. Hi, I’d like to have the post content weight be a lower priority, how do I code this?

    Cheers,
    Laura

  11. Cool feature, thanks Mikko. I’m wondering, though, if it’s possible to weigh results based on a post type of “user”? We’re including users along with a few usermeta fields in our index, and we’d like users to come back with a much higher priority. (We’re only displaying users that are “members”, through custom code on the search results side.)

    I do not see post type “user” in the Weights section of the Relevanssi Premium settings, and I’m not sure of the code above would work with user post types.

    1. Ah, indeed, users are missing in the settings. The code above does work, you can use it to adjust the weight for users. Users have a post type of “user”.

      1. Thanks Mikko. I am just not understanding where I would specify a post type in the code here. There are the date-based and custom field-based weights, but is there a “post type” weight hook? A code example would be awesome if you have one. Thank you!

  12. When I built my site, I use pages to house products. Is there a way to set a custom weight per page? For EG: I want to search for a product name, but I have 5 other pages with the same keyword that are sub-pages, and my sub-pages are showing up before my parent page. Is there a way I can set a weight for parent pages?

    1. With Relevanssi Premium, an easy solution would be to pin the parent page for the keyword. That would guarantee that when someone searches for that keyword, the parent page comes up first.

      Other solutions involve writing functions that either adjust the weights using the relevanssi_match filter hook or manipulate the order of the results using the relevanssi_hits_filter filter hook.

  13. Is there a way to increase the weight by popularity or amount of views of the page/post/document.

    1. Yes, it’s described on this very page. Create a relevanssi_match filter that adjusts the weight based on the data. If you can get the popularity based on post ID and can tell how popular a post is compared to other posts, it’s possible to create a filter that boosts the weight of popular posts. Not a bad idea!

  14. Awesome plugin! I see a comment from several years ago that this is a Premium feature only- is that still true? Or am I just doing this wrong? Can’t seem to get priority on the search term being in page/post/CPT titles.

    Thanks!

    1. No, that was five years ago. It’s also available in free version. But you shouldn’t need any code – just up the title weight to, say, 1000 in Relevanssi settings, and you should see the titles given much higher priority.

  15. Just installed Relevanssi and built the index. Is it possible (as it says in the description of the plugin) to increase the search score for a post where the search term(s) matches the post’s tags ?

    1. PeO, in Relevanssi Premium there’s a simple setting for that. In the free version, follow the instructions on this page under “Weight from taxonomy terms”, as tags are taxonomy terms in the taxonomy “post_tag”.

      1. Added that code, and increased multiplier to 5000 to be sure it has some effect.. did no difference. Is there some search result caching in the tables added by Relevanssi ? Is there any way to clear that cache (this might been in another plugin, which stated there is a cache that is used an hour from the last search with the same term).

        Is it possible to add some index to the Relevanssi-tables to speed up the search ? It’s night over in US where the site I’m working with is located, still the searches take several seconds. Might annoy users.

      2. Might have found a bug or feature.. When I do a search, while not logged in (as an ordinary user), I get the two posts matching the term at the top. Logging in with my user at the site (not admin), I get another result (51 matches instead of only 8 not logged in), and those matching the tags are no longer the two first results.

      3. Found the reason for different number of hits. We are using s2Member, so my user has access to all the posts, while the anonymous one has not.
        We want to include search hits to the protected articles in the result.
        The scoring problem is still relevant, when I get the full search result of 51 posts, those with the tags are located at the third and fifth page.

        1. In order to disable the s2member filter, you need to add a new filter that overrides the default filter.

          add_filter('relevanssi_post_ok', 'rlv_disable_s2member', 11, 2);
          function rlv_disable_s2member($ok) {
          	$status = relevanssi_get_post_status($doc);
          	if ('publish' != $status) {
          		$ok = false;
          	}
          	// only show drafts, pending and future posts in admin search
          	if (in_array($status, apply_filters('relevanssi_valid_admin_status', array('draft', 'pending', 'future'))) && is_admin()) {
          		$ok = true;
          	}
          	return $ok;
          }

          That should show you all posts.

          Relevanssi doesn’t have any caching, so that’s not the issue. If you enable the search results breakdowns, does adjusting the value increase the relevancy score? If not, then there’s a mistake in the code. You have the correct taxonomy there?

          Relevanssi already has the indices it needs. How big is your site, how many posts approximately in the index? Make sure “Throttle searches” is enabled on the Searching tab in the Relevanssi settings. That should speed up the search if it’s not enabled. Also, make sure your excerpts are based on words and not characters. Character-based excerpts can be really slow.

  16. Adding that exact code broke the search, just giving a default “post” with the title “Untitled” and a “read more” button on the result page (how do I fix this, before Relevanssi, I had a page telling the user that no results was found, and presented a new search form ?) when not logged in.

    The code for changing weight for posts with matching tags does work, but 5000 seems like a too small value to compensate for the other articles that matches when logged in. For some reason these get the a score above 4 million when the code is active:

    add_filter('relevanssi_match', 'rlv_boost_all_terms');
    function rlv_boost_all_terms($match) {
    if (has_term("", "post_tag", $match->doc)) $match->weight = $match->weight * 5000;
    return $match;
    }

    The two first hits are scored about 1000 when I have commented out the filter code for increasing weight, and those posts aren’t even tagged with the word I search for (no tags at all in these, which could be the problem)
    The index contains more or less statically around 1200 posts.

  17. So what exactly is the result you want to get when a non-member searches for a protected post?

    The rlv_boost_all_terms() function currently gives the boost for all posts that have any tags. Perhaps that’s not what you wanted in the first place?

    add_filter('relevanssi_match', 'rlv_boost_term_matches');
    function rlv_boost_term_matches($match) {
        if ($match->taxonomy > 0) $match->weight = $match->weight * 100;
        return $match;
    }

    This will boost posts where the search term matches any taxonomy (except category). There’s no easy way in the free Relevanssi to know which taxonomy matches the search; that’s a Premium feature.

  18. I want the same result for non-members as for members, the non-members will then be able to see a short excerpt (as generated by Relevanssi where the term was found), but not the full article.

    Now that suggested code (for disabling s2Member) breaks the search and gives no results at all (instead of the 8 posts that are open), not even logged in as site admin (which indicates broken code).

    ‘rlv_boost_term_matches’ seems to do the correct increasing of the score for now. I’ve also added in ‘rlv_boost_all_terms’, so that posts with any tag will count as a better match (just *2).

  19. I created this snippet to add weight to author names in search results. Make sure you check the box to index author display names!

    Searching for Mikko is more likely to show posts by Mikko, than posts who mention Mikko in the content. 🙂

    function aa_relevanssi_weight_authors( $match ) {
    	$post = get_post( $match->doc );
    	if ( empty($post->post_author) ) return $match;
     
    	$display_name = get_the_author_meta( 'display_name', $post->post_author );
    	$first_name = get_the_author_meta( 'first_name', $post->post_author );
    	$last_name = get_the_author_meta( 'last_name', $post->post_author );
     
    	// Improve relevance if the search matches a post author's display name, or first/last name.
    	if ( stripos($display_name, $match->term) !== false ) { $match->weight *= 2; }
    	else if ( stripos($first_name, $match->term) !== false ) { $match->weight *= 1.5; }
    	else if ( stripos($last_name, $match->term) !== false ) { $match->weight *= 1.5; }
     
    	return $match;
    }
    add_filter( 'relevanssi_match', 'aa_relevanssi_weight_authors' );
  20. I think I got it … you can clean out the comments and write a summary how to include results from protected s2Member pages and posts..

    Just a setting in s2Member:
    Under s2Member settings, “Restriction Options”:
    Alternate View Protection (feeds, search results, etc.)
    * Uncheck “Filter all WordPress queries”
    * Check everything but “Searches” (or as you wish)

    The filter ‘rlv_disable_s2member’ for ‘relevanssi_post_ok’ is not needed.

    1. Thanks, looks like s2member has indeed changed the way it works, and the Relevanssi controls for s2member are not used at all anymore, it’s all coming from s2member.

  21. Can I give a users with a certain role a higher weight than other users posts?
    I need it to still show in order of search term matches, but then if two users posts have the same amount of matches then it show the users with the role premium before the user with the role member.
    Is this possible?
    If not, is it possible to do same as above but with post types? So for example if I had post-types of: Premium-posts and basic-posts, Still going by search results match, but show the premium-posts before basic-posts when both posts have same amount of matches?

    Thanks – LOVE THIS PLUGIN BY THE WAY!

    1. Chantelle, sure. It’s pretty difficult to do it as a secondary sorting parameter, but giving a small extra boost (like 1.1 multiplier) is easy to do, and has pretty much the same effect.

      You can do this with the relevanssi_match filter: the post ID is in $match->doc, so you can use that to get the post author ($post = get_post($match->doc); $user = get_userdata($post->post_author);) and with the user object you can get the role and so on.

  22. Thanks for this! Was looking for the Date-based weight filter and customized it to fit my needs making the effect over time be more gentle.

Leave a Reply

Are you a Relevanssi Premium customer looking for support? Please use the Premium support form.

Your email address will not be published. Required fields are marked *