Les rédacteurs de notre grande installation Wordpress adorent utiliser la fonctionnalité de recherche de contenu. Aussi pratique que soit cette fonctionnalité, la complexité de ses requêtes ralentit considérablement notre base de données. Voici un exemple d'une requête SQL trouvée dans notre journal de requête lent il y a quelques minutes à peine:
SELECT SQL_CALC_FOUND_ROWS wp_posts.ID
FROM wp_posts
WHERE 1=1
AND (
((wp_posts.post_title LIKE '%Made%') OR (wp_posts.post_content LIKE '%Made%'))
AND ((wp_posts.post_title LIKE '%in%') OR (wp_posts.post_content LIKE '%in%'))
AND ((wp_posts.post_title LIKE '%the%') OR (wp_posts.post_content LIKE '%the%'))
AND ((wp_posts.post_title LIKE '%shade:%') OR (wp_posts.post_content LIKE '%shade:%'))
AND ((wp_posts.post_title LIKE '%Easy%') OR (wp_posts.post_content LIKE '%Easy%'))
AND ((wp_posts.post_title LIKE '%tips%') OR (wp_posts.post_content LIKE '%tips%'))
AND ((wp_posts.post_title LIKE '%to%') OR (wp_posts.post_content LIKE '%to%'))
AND ((wp_posts.post_title LIKE '%care%') OR (wp_posts.post_content LIKE '%care%'))
AND ((wp_posts.post_title LIKE '%for%') OR (wp_posts.post_content LIKE '%for%'))
AND ((wp_posts.post_title LIKE '%your%') OR (wp_posts.post_content LIKE '%your%'))
AND ((wp_posts.post_title LIKE '%outdoor%') OR (wp_posts.post_content LIKE '%outdoor%'))
AND ((wp_posts.post_title LIKE '%furniture%') OR (wp_posts.post_content LIKE '%furniture%'))
)
AND wp_posts.post_type = 's5_post'
AND (
wp_posts.post_status = 'publish'
OR wp_posts.post_status = 'future'
OR wp_posts.post_status = 'draft'
OR wp_posts.post_status = 'pending'
OR wp_posts.post_status = 'private'
)
ORDER BY wp_posts.post_date DESC LIMIT 0, 20
Découvrez la taille de ce gars! Ce n'est pas étonnant que cela fonctionne lentement.
Je serais intéressé d'entendre des idées sur la façon de coder quelques modifications à cette fonctionnalité pour la rendre un peu plus efficace. (J'ai déjà quelques idées personnelles; j'espère que les vôtres sont meilleures que les miennes! :))
WHERE
Un filtre nommé posts_search
permet de filtrer la clause SQL WHERE
utilisée pour la requête lors de la recherche (lorsque WP_Query::is_search()
renvoie true et que WP_Query->s
est défini):
add_filter( 'posts_search', 'wpse134392PostsSearchSQL', 20, 2 );
function wpse134392PostsSearchSQL( $sql, $wp_query )
{
// Alter SQL clause here
return $where;
}
ORDERBY
Pour intercepter l'instruction ORDERBY
(par exemple, pour trier par auteur afin que l'auteur de la recherche obtienne ses publications en premier/dernier), vous pouvez utiliser posts_search_orderby
:
add_filter( 'posts_search_orderby', 'wpse134392PostsSearchOrderbySQL', 20, 2 );
function wpse134392PostsSearchOrderbySQL( $orderby, $wp_query )
{
if ( is_admin() )
return $GLOBALS['wpdb']->posts."post_date";
return $orderby;
}
Vous pouvez également modifier le posts_clauses
ou le pre_get_posts
pour obtenir des résultats encore plus précis en vérifiant dans votre rappel si is_admin()
et $query->is_search()
sont TRUE
.
Pour exclure les termes courants qui ne vous aideront pas, vous pouvez utiliser WP_Query::get_search_stopwords()
- ou mieux: Un rappel sur le filtre. Actuellement, les mots vides sont:
about,an,are,as,at,be,by,com,for,from,how,in,is,it,of,on,or,that,the,this,to,was,what,when,where,who,will,with,www
Un exemple de rappel de filtre:
add_action( 'wp_search_stopwords', 'wpse134392SearchStopwords' );
function wpse134392SearchStopwords( $stopwords )
{
return $stopwords + array(
'my',
'your',
'easy',
);
}
Astuce: Il semble que quelque chose (un plugin probablement) intercepte déjà votre rappel car il contient des mots qui ne devraient pas être recherchés.
Je recommanderais de changer votre requête avec $ args étant quelque chose comme ça
$args = array(
'post_status' => array('pending', 'draft', 'future' ),
'post_type' => array( 'post', 'page', 'movie', 'book' ),
'orderby' => 'date',
'order' => 'DESC',
's' => 'keyword'
);
$search_query = new WP_Query($args);
Il y a aussi une description plus détaillée ici . La seule chose que je n'arrive pas à trouver est de rechercher plusieurs mots clés. Peut-être que si vous faites quelque chose comme ça ça pourrait marcher
's' => 'keyword1+keyword2+keyword3'