WP_Query возвращает случайные идентификаторы в запросах таксономии с аргументом posts_per_page

#mysql #wordpress

#mysql #wordpress

Вопрос:

Я пытаюсь получить последние идентификаторы продуктов из определенной категории WooCommerce. По какой-то причине при каждой загрузке страницы я получаю разные идентификаторы продуктов, а не самые последние.

Вот аргументы WP_Query:

 array(
    'post_type' => 'product',
    'posts_per_page' => 5,
    'tax_query' => array(
        array(
            'taxonomy' => 'product_cat',
            'field' => 'slug',
            'terms' => 'a-product-category' 
        )
    ),
    'orderby' => 'date',
    'order' => 'ASC'
)
  

Это генерирует следующий SQL-запрос:

 SELECT SQL_CALC_FOUND_ROWS wp_posts.ID
FROM wp_posts
LEFT JOIN wp_term_relationships
ON (
    wp_posts.ID = wp_term_relationships.object_id
)
WHERE 1=1
AND (
    wp_term_relationships.term_taxonomy_id IN (259,260,262)
)
AND wp_posts.post_type = 'product'
AND (
    wp_posts.post_status = 'publish' OR wp_posts.post_status = 'private'
)
GROUP BY wp_posts.ID
ORDER BY wp_posts.post_date ASC
LIMIT 0, 5
  

Как я уже сказал, возвращаемые идентификаторы post всегда несколько отличаются (хотя они относятся к правильной категории). Я понимаю, что правильное поведение для этого запроса заключается в том, что он должен возвращать пять последних сообщений из указанной категории.

Я выполнил запрос непосредственно на SQL-сервере, чтобы исключить любые проблемы с WordPress или плагинами, и все равно получил случайные идентификаторы сообщений.

Если я удалю tax_query (удалю команды SQL, связанные с wp_term_relationship) или установлю posts_per_page равным -1 (удалит ОГРАНИЧЕНИЕ 0, 5), идентификаторы post будут в правильном порядке.

Однако это работает так, как я думаю, что это должно работать на моем сервере разработки. Это происходит на рабочем сервере (который использует WPEngine в качестве хостинг-провайдера и MySQL 5.6.32).

Любые советы приветствуются, спасибо!

Ответ №1:

Похоже, это было связано с тем, что если вы попытаетесь работать ORDER BY с неуникальными данными, результаты могут отличаться от ожидаемых, особенно в кластеризованной среде MySQL (которую, я думаю, использует WPEngine). В этом случае post_date это было одинаково для нескольких сообщений, потому что я использовал импортер для их создания.

То же самое произошло, когда я попытался отсортировать товары по цене, и некоторые товары имели одинаковые цены.

Чтобы решить эту проблему в WP_Query, я использовал запасной order_by вариант аргумента:

 'order_by' => 'date ID'
  

Который преобразуется в SQL-запрос:

 ORDER BY wp_posts.post_date ASC, wp_posts.ID ASC
  

Более подробную информацию об этой проблеме можно найти здесь: https://bugs.mysql.com/bug.php?id=69732