WP_Query -> sort results by relevance (= most tags / taxonomy terms in common)

I’m trying to write a new “related posts” widget (for the single post view) for my custom post type, filtering by custom taxonomy terms that the related posts should have in common with the current post. I found this solution.

But what I’d like to add is that the posts are ordered by relevance. I determine the relevancy by the number of taxonomy terms that they have in common: The more taxonomy terms in common, the more relevant.

Read More

Example: Current post has tags (1), (2), (3) and (4). A related post with tags (1), (3) and (4) is more relevant than a related post with only the tags (1) and (2).

Also, if possible, I’d like to add special severity/emphasis to one of the custom taxonomy terms (which I assume to be the “main” term of a post).

Example: Current post has tags (1), (2), (3) and (4). (1) is the main term of the post. Posts should only be displayed as related posts, if they have at least this main term in common. A related post with tags (1) and (3) is more relevant than a related post with the tag (1) only. (Optional: A post with the tags (2), (3) and (4) is not considered a related post, or: this post has a lower relevance than any post that has the main term (1) in common.)

Can you please help me with this? Thanks in advance! 🙂

Regards,
René

Related posts

Leave a Reply

1 comment

  1. Sorting your posts by relevance

    This will need to add an extra propperty to each post. Than sort the object by this new prperty. The trick is to sort the posts directly in the query object.

    function get_posts(){
    
      // get the posts but do NOT order them  
        $query_posts = new WP_Query( array( 'numberposts' => 5 ) );
    
      // calculate the relevance for each post
        foreach( $query_posts->posts as $post )    
            $post->relevance = calculate_relevance( $post );
    
      // sorting the posts 
        usort( $query_posts->posts, 'compare' );
    
       return $query_posts;
    
    }
    
    function calculate_relevance( $post ){
        // calculate the relevance of the post here
        return rand( 0, 100 );
    
    }
    
    function compare( $a, $b ){
    
        if(  $a->relevance ==  $b->relevance )
            return 0;
    
        return ( $a->relevance > $b->relevance ) ? -1 : 1;
    
    }
    
    $posts = get_posts();
    
    // output the sorted posts
    while( $posts->have_posts() ){
    
      $posts->the_post();
    
      echo the_title() . '<br>';
    
    }
    

    This will output the posts ordered by your calculated relevance.


    Severity/Emphasis

    Calculating a severity or emphasis is just a bunch of if then else blocks.

    Pseudo code:

    ...
      $post->emphasis = get_post_emphasis( $post, 'main_term' );
    ...
    
    function get_post_emphasis( $post, $main_term ){
    
      $emphasis = 0;
      $terms = get_posts_terms( $post ); // $terms is an array
    
      if( in_array( $main_term, $terms ) )
        $emphasis++;
    
      if( in_array( $main_term, $terms ) && 2 < count( $terms) )
        $emphasis++;
    
      return $emphasis;
    
    }
    

    But how do you want to mark a term as ‘main term’?