SearchWP

Version 4 Documentation

Add Relevance Weight to More Recently Published Entries by Date

Note: This documentation is for SearchWP 4
SearchWP 3.x: Add Weight to More Recently Published Entries

By default SearchWP returns results sorted by the total calculated weight based upon the values entered in your engine configuration. There are times when you might want to dynamically influence the ranking of search results by taking into consideration the publish date of each result.

Using SearchWP’s searchwp\query\mods hook, we can do just that! There are three different approaches to cover:

Note: This implementation does NOT cause results to be sorted by date, instead more recently published entries will simply be given more weight as calculated by SearchWP. The more recently an entry was published the more weight it gets.

See also: Using a Custom Field to Prioritize Search Results

Bonus weight for recently published

To have more recently published entries get a weight boost, add this to your SearchWP Customizations plugin:

All hooks should be added to your custom SearchWP Customizations Plugin.

<?php
// Add search weight to more recently published entries in SearchWP.
add_filter( 'searchwp\query\mods', function( $mods ) {
global $wpdb;
$mod = new \SearchWP\Mod();
$mod->set_local_table( $wpdb->posts );
$mod->on( 'ID', [ 'column' => 'id' ] );
$mod->relevance( function( $runtime ) use ( $wpdb ) {
return "
COALESCE( ROUND( ( (
UNIX_TIMESTAMP( {$runtime->get_local_table_alias()}.post_date )
- (
SELECT UNIX_TIMESTAMP( {$wpdb->posts}.post_date )
FROM {$wpdb->posts}
WHERE {$wpdb->posts}.post_status = 'publish'
ORDER BY {$wpdb->posts}.post_date ASC
LIMIT 1
)
) / 86400 ), 0 ), 0 )";
} );
$mods[] = $mod;
return $mods;
} );

Bonus weight that decays over time

Alternatively, you can use something like this to have the weight influence taper off as publish dates go further back in time. Only recently published posts will get a boost, the published date for older posts will not influence the weight.

This modification is more aggressive in that the influence tapers off over time, but that may be preferential for you!

All hooks should be added to your custom SearchWP Customizations Plugin.

<?php
// Add search weight to more recently published entries in SearchWP.
// Weight decays over time and eventually will not add bonus weight.
add_filter( 'searchwp\query\mods', function( $mods ) {
global $wpdb;
$weight_adjust = 15;
$mod = new \SearchWP\Mod();
$mod->set_local_table( $wpdb->posts );
$mod->on( 'ID', [ 'column' => 'id' ] );
$mod->relevance( function( $runtime_mod ) use ( $weight_adjust ) {
$alias = $runtime_mod->get_local_table_alias();
return "
( 100 * EXP(
( 1 - ABS( (
UNIX_TIMESTAMP( {$alias}.post_date )
- UNIX_TIMESTAMP( NOW() )
) / 86400 ) ) / 1 )
* {$weight_adjust} )";
} );
$mods[] = $mod;
return $mods;
} );

With either in place, entries with more recent published dates will be given more weight than those with older publish dates.

As referenced in the comment, experiment with line 8 to determine what $modifier value works best for you.

Date stored as Custom Field value

Another example would be to have results sorted by dates stored in a Custom Field. The more recent the date of the Custom Field the more weight the result will receive:

All hooks should be added to your custom SearchWP Customizations Plugin.

<?php
// Add bonus weight from Custom Field value in SearchWP.
add_filter( 'searchwp\query\mods', function( $mods ) {
global $wpdb;
// Custom Field name. Needs to store data as YYYYMMDD (ACF does this already).
$my_meta_key = 'date_field';
$mod = new \SearchWP\Mod();
$mod->set_local_table( $wpdb->postmeta );
$mod->on( 'post_id', [ 'column' => 'id' ] );
$mod->on( 'meta_key', [ 'value' => $my_meta_key ] );
$mod->relevance( function( $runtime ) use ( $wpdb, $my_meta_key ) { return $wpdb->prepare( "
COALESCE( ROUND( ( (
UNIX_TIMESTAMP( {$runtime->get_local_table_alias()}.meta_value )
- (
SELECT UNIX_TIMESTAMP( meta_value )
FROM {$wpdb->postmeta}
WHERE meta_key = %s
ORDER BY meta_value ASC
LIMIT 1
)
) / 86400 ), 0 ), 0 )", $my_meta_key );
} );
$mods[] = $mod;
return $mods;
} );

Arbitrary multiplier on date as Custom Field value

It is also possible to arbitrarily assign a multiplier to the final, calculated weight (relevance) of results. In other words, the weight manipulation will not be dynamic based on the timestamp, but instead multiplied by a value you determine.

You can apply different multipliers based on whether the Custom Field date is in the past or the future, reducing the calculated relevance if the Custom Field value is in the past, and increasing calculated relevance if it’s in the future for example:

All hooks should be added to your custom SearchWP Customizations Plugin.

<?php
// Modify SearchWP calculated relevance using multiplier.
// @link https://searchwp.com/documentation/knowledge-base/add-relevance-weight-date/
class My_SearchWP_Date_Modifier {
private $post_type = 'post';
private $meta_key = 'event_date';
private $modifier_past = 0.5;
private $modifier_future = 1.5;
private $alias = 'myswpdm';
function __construct() {
global $wpdb;
// Modify SearchWP calculated relevance using multiplier.
add_filter( 'searchwp\query', function( $query, $args ) use ( $wpdb ) {
// Calculate a CUSTOM relevance.
$query['select'][] = "( SUM(relevance) * {$this->alias}mod ) AS {$this->alias}rel";
// Implement a custom weight modifier based on date stored as meta value.
$query['from']['select'][] = "
(
CASE
WHEN UNIX_TIMESTAMP( {$this->alias}m.meta_value ) < UNIX_TIMESTAMP( NOW() )
THEN {$this->modifier_past}
WHEN UNIX_TIMESTAMP( {$this->alias}m.meta_value ) > UNIX_TIMESTAMP( NOW() )
THEN {$this->modifier_future}
ELSE 1
END
) AS {$this->alias}mod
";
// Custom JOINs.
$query['from']['from'][] = "
LEFT JOIN {$wpdb->posts} {$this->alias}p
ON ( {$this->alias}p.ID = {$args['index_alias']}.id
AND {$this->alias}p.post_type = '{$this->post_type}' )
";
$query['from']['from'][] = "
LEFT JOIN {$wpdb->postmeta} {$this->alias}m
ON ( {$this->alias}m.post_id = {$this->alias}p.ID
AND {$this->alias}m.meta_key = '{$this->meta_key}' )
";
// Use our custom relevance to sort results by overriding the default ORDERBY.
$query['order_by'] = [ "{$this->alias}rel DESC", ];
return $query;
}, 20, 2 );
}
}
new My_SearchWP_Date_Modifier();

The overall implementation of the above snippet is that we’re manipulating SearchWP’s query directly to:

  1. Add a new column to the index query to calculate and store our custom relevance calculation
  2. Add a modifier calculation based on the UNIX_TIMESTAMP of the Custom Field value
  3. Include custom JOINs to ensure we’re retrieving the proper Custom Field values
  4. Override SearchWP’s ORDERBY clause to sort results by our custom relevance calculation

By taking this approach we can have full and direct control over how SearchWP’s query runs and in this case adjust the calculated weight for Posts with a Custom Field named event_date using a direct multiplier, leaving other post types (or Posts without the Custom Field) unaffected by the multiplier.