Почему post__not_in лучше не использовать?

Параметр WP_Query post__not_in супер-полезен, как минимум с его помощью можно исключать текущий пост, когда выводите похожие посты. Однако для высоконагруженных сайтов это может привести к моментикам с производительностью, потому что использование этого параметра исключает возможность кэширования запроса.

Вот допустим пример вывода последних постов на странице поста, но с исключением из цикла текущего поста:

$exclude_id = get_the_ID();
 
$args = array(
	'posts_per_page' => 10,
	'post_status' => 'publish',
	'post__not_in' => array( $exclude_id ),
);
 
$recent_posts = new WP_Query( $args );
 
echo '<h2>Свежие посты</h2>';
 
while( $recent_posts->have_posts() ) : $recent_posts->the_post();
	the_title( '<h3><a href="' . get_permalink() . '">', '</a></h3>' );
endwhile;
 
wp_reset_postdata();

Выглядит как лёгкое и чистое решение, не так ли? Но не спешите радоваться, ведь как раз от подобного решения мы сейчас и будем пытаться уйти.

Объясняю почему.

Дело в том, что запрос, который мы построили выше, теперь будет уникальным для каждого поста, потому что в нём будет присутствовать часть AND ID NOT IN ( '12345' ), это по сути и ломает идею кэширования, потому что так как запрос уникальный, то и кэш будет уникальным для каждого запроса и в итоге, вместо того, чтобы всего-то получить последние посты из кэша, у нас будет происходить подключение к базе данных и полноценно вся работа.

Конечно, на обычных сайтах это не сильно нас напряжёт, но на сайтах с сотнями тысяч постов вы это точно почувствуете.

Как же мы можем переделать наш предыдущий пример в таком случае?

$exclude_id = get_the_ID();
 
// мы знаем, что один пост вероятно исключим, поэтому получаем не 10, а 11
$args = array(
	'posts_per_page' => 11,
	'post_status' => 'publish'
);
 
$recent_posts = new WP_Query( $args );
 
echo '<h2>Свежие посты</h2>';
 
// нам понадобится счётчик, потому что не факт, что исключаемый пост будет в цикле
// а значит без счётчика у нас будет выводиться то 10, то 11 – не порядок
$count = 0;
 
while( $recent_posts->have_posts() && $count < 10 ) : $recent_posts->the_post();
 
	if( $recent_posts->post->ID === $exclude_id ) {
		continue; // скипаем итерацию цикла, если это исключаемый пост
	}
 
	the_title( '<h3><a href="' . get_permalink() . '">', '</a></h3>' );
	$count++;
endwhile;
 
wp_reset_postdata();

Источник: Блог Миши Рудрастых

Миша Рудрастых

Путешествует по миру и рассказывает всем о WordPress лично, у себя в блогах и на курсах в Санкт-Петербурге. Умеет просто объяснять сложные вещи, делает это красиво. Организовывает неплохие WordCamp's, но совсем не умеет слушать чужие доклады.

Добавить комментарий

%d такие блоггеры, как: