Здравствуйте. Есть тип записи у которого почти пол миллиона постов. Раньше когда постов было меньше 2000 фильтрация по meta_query работала быстро. Но сейчас когда постов больше 400к загрузка длится от 5 минут. Судя по информации в различных форумах дело именно в фильтрации по метаполям. Но у меня много полей которые участвуют в фильтрации и менять 400к записей под таксономии будет проблематично. Есть ли какой то способ ускорить фильтр постов в wp_query используя meta_query? На страницу вывожу по 5 штук. Ведь выборка не должна отобрать первые 5 записей подходящих и выдать результат, просто почему так долго?
Пример кода(урезанный вариант):
// $template = $_POST["template"];
$args['post_type'] = 'objects';
$args['post_status'] = 'publish';
$args['posts_per_page'] = 10;
// СОРТИРОВКА
// по цене
if (!empty($_POST["sortByPrice"])) {
$args['meta_key'] = 'price';
$args['orderby'] = 'meta_value_num';
$args['order'] = $_POST["sortByPrice"];
$args['ignore_custom_sort'] = true;
}
$args['meta_query'] = array(
'relation' => 'AND'
);
// Страница
if (!empty($_POST["page"])) {
$args['paged'] = $_POST["page"];
}
// META
// Цена ОТ
if (!empty($_POST["priceFrom"])) {
$args['meta_query'][] = array(
'key' => 'price',
'value' => $_POST["priceFrom"],
'type' => 'NUMERIC',
'compare' => '>'
);
}
// Цена ДО
if (!empty($_POST["priceTo"])) {
$args['meta_query'][] = array(
'key' => 'price',
'value' => $_POST["priceTo"],
'type' => 'NUMERIC',
'compare' => '<'
);
}
// Площадь ОТ
if (!empty($_POST["squareFrom"])) {
$args['meta_query'][] = array(
'key' => 'square',
'value' => $_POST["squareFrom"],
'type' => 'NUMERIC',
'compare' => '>'
);
}
// Площадь ДО
if (!empty($_POST["squareTo"])) {
$args['meta_query'][] = array(
'key' => 'square',
'value' => $_POST["squareTo"],
'type' => 'NUMERIC',
'compare' => '<'
);
}
// Тип сделки
if(!empty($_POST["dealType"])) {
$objCategories[] = $_POST["dealType"];
}
// вторичное
if($_POST["street"] == 'вторичное') {
$objCategories[] = 'real-estate-apartments-sale-secondary';
}
if(!empty($_POST["dealType"]) or $_POST["street"] == 'вторичное') {
$args['tax_query'][] = array(
'taxonomy' => 'obj_categories',
'field' => 'slug',
'terms' => $objCategories,
);
}
// Только с фото
if (!empty($_POST["withPhotos"])) {
$args['meta_query'][] = array(
array(
'key' => 'gallery',
'value' => array('', 0),
'compare' => 'NOT IN'
)
);
}
// Только с газом
if (!empty($_POST["gas_type"])) {
$args['meta_query'][] = array(
array(
'key' => 'gas_type_name',
'value' => array('', 0),
'compare' => 'NOT IN'
)
);
}
// Кол-во комнат
// TODO: Нужно найти все совпадения
if (!empty($_POST["rooms"])) {
$args_for_rooms = array(
'relation' => 'OR'
);
$arrayRooms = explode(",", $_POST["rooms"]);
foreach ($arrayRooms as $key => $value) {
// $value = 0,1,2,3,4+
switch ($value) {
case '4+':
$array_for_four = [
'relation' => 'AND'
];
$array_for_four[] = array(
'key' => 'rooms',
'value' => 3,
'compare' => '>'
);
// исключаю студии, так студия = 6 символов и они присутствуют в выдаче
if (!in_array('studia', $arrayRooms)) {
$array_for_four[] = array(
'key' => 'rooms',
'value' => array('студия', '', '-'),
'compare' => 'NOT IN'
);
}
$args_for_rooms[] = $array_for_four;
break;
case 3:
case 2:
case 1:
$args_for_rooms[] = array(
'key' => 'rooms',
'value' => $value,
'compare' => 'IN'
);
break;
case 'studia':
$args_for_rooms[] = array(
'key' => 'rooms',
'value' => array('студия'),
'compare' => 'IN'
);
break;
}
}
$args['meta_query'][] = $args_for_rooms;
}
// Поиск в названии (улица и тд)
if (!empty($_POST["street"])) {
//$args['obj_title'] = $_POST["street"]; // добавялю в массив args
$args['s_meta_keys'] = array('title', 'tags');
$args['s'] = $_POST["street"];
}
function title_filter($where, &$wp_query)
{
global $wpdb;
// check if $_POST['novostroi'] exists
if (!empty($_POST['novostroi'])) {
// exclude posts with "участок" in their title
$where .= ' AND ' . $wpdb->posts . '.post_title NOT LIKE \'%участок%\'';
$where .= ' AND ' . $wpdb->posts . '.post_title NOT LIKE \'%коммерч%\'';
$where .= ' AND ' . $wpdb->posts . '.post_title NOT LIKE \'%дом%\'';
}
if ($search_term = $wp_query->get('obj_title')) {
$where .= ' AND ' . $wpdb->posts . '.post_title LIKE \'%' . esc_sql(like_escape($search_term)) . '%\'';
}
return $where;
}
add_filter('posts_where', 'title_filter', 10, 2);
add_filter('posts_where', 'yanco_posts_where');
function yanco_posts_where( $where ) {
$where = str_replace( "meta_key = 'metro_station_$", "meta_key LIKE 'metro_station_%", $where );
return $where;
}
$args['no_found_rows'] = true;
$posts = new WP_Query($args);
$response_array = array();
remove_filter('posts_where', 'title_filter', 10, 2);
if ($posts->have_posts()) {
$response_array['success'] = true;
while ($posts->have_posts()) {
$posts->the_post();
ob_start();
get_template_part("template-parts/loop/object-item-new");
$response_array['html'] .= ob_get_contents();
ob_end_clean();
}
} else {
$response_array['success'] = false;
}
$response_array['args'] = $args;
$response_array['$_POST'] = $_POST;
wp_send_json($response_array);
wp_die();