Get related posts matching most of the provided tags using WP_Query

There is no direct way of getting posts matching most of these tags using WP_Query.

The usual documented methods:

If you want posts matching any of these tags, you may use:

$args = array(
    'post_type' => 'post',
    'tag_slug__in' => array( 'poetry', 'motivational', 'attitude', 'rules', 'lines', 'sigma', 'inspirations' )
$query = new WP_Query( $args );

Also, if you want posts matching all of these tags, you may use:

$args = array(
    'post_type' => 'post',
    'tag_slug__and' => array( 'poetry', 'motivational', 'attitude', 'rules', 'lines', 'sigma', 'inspirations' )
$query = new WP_Query( $args );

Getting posts with most of these tags:

To achieve what you want, you’ll have to either use a custom SQL query or some advanced customizations to the WP_Query generated SQL query using hooks.

For example, you may use the posts_clauses hook combined with pre_get_posts hook to alter the SQL generated by WP_Query.

To get posts with most of these tags, you’ll need to include count( wp_term_relationships.object_id) in SELECT portion of the generated SQL query, and then sort the query result by that count in descending order.

The following is the code of a complete plugin that implements this logic:

 * Plugin Name: Related posts by most tags
 * Description: Show related posts by of the provided tags
 * Author: Fayaz Ahmed
 * Version: 1.0.0
 * Author URI:

namespace Fayaz\dev;

 * Any WP_Query where 'order_by_most_tags' is set as an argument,
 * will be altered by this function, so that the query result is 
 * ordered by the number of matching tags in descending order.
 * However, if no matching tag is provided, then that query will not
 * be altered by this.
function filter_posts_by_most_tags( $query ) {
    if( isset( $query->query['order_by_most_tags'] )
        && isset( $query->query_vars['tag_slug__in'] ) && ! empty( $query->query_vars['tag_slug__in'] ) ) {
        add_filter( 'posts_clauses', '\Fayaz\dev\add_select_count_tags', 10, 2 );
add_action( 'pre_get_posts', '\Fayaz\dev\filter_posts_by_most_tags' );

function add_select_count_tags( $clauses, $wp_query ) {
    global $wpdb;

    // database query modification needed for ordering based on most tags
    $clauses['fields'] = $clauses['fields'] . ', count( ' . $wpdb->term_relationships . '.object_id ) as number_of_tags';
    $clauses['orderby'] = 'number_of_tags DESC, ' . $clauses['orderby'];

    // we only need this once, so it's better to remove the filter after use
    remove_filter( 'posts_clauses', '\Fayaz\dev\add_select_count_tags', 10, 2 );
    return $clauses;

Sample Plugin Usage:

The above plugin implements a custom WP_Query argument named order_by_most_tags. When it’s set, the plugin will alter the result to get posts with most of the provided tags.

One you activate the plugin, use the code as shown below in your currently active theme’s template files (e.g. single.php):

$args = array(
    'post_type' => 'post',
    'tag_slug__in' => array( 'poetry', 'motivational', 'attitude', 'rules', 'lines', 'sigma', 'inspirations' ),
    'order_by_most_tags' => 1,
    // other order by (in case there are multiple matches with most tags)
    'orderby' => array( 'comment_count' => 'DESC', 'date' => 'ASC' )
$post_ID = get_the_ID();
if( $post_ID ) {
    // exclude current post
    $args['post__not_in'] = array( $post_ID );
echo '<h2>Related Posts</h2>';
$query = new WP_Query( $args );
if ( $query->have_posts() ) {
    echo '<ul>';
    while ( $query->have_posts() ) {
        echo '<li>';
            <a href="<?php the_permalink(); ?>" title="<?php the_title_attribute(); ?>"><?php the_title(); ?></a>
        echo '</li>';
    echo '</ul';
else {
    echo '<h2>Nothing is found</h2>';
// Restore original Post Data, needed if this was run in a loop