Existe-t-il un moyen de définir un alias sur les arguments meta_query lors de l'exécution d'un get_posts()
? L'une de mes requêtes fonctionne mal. Pour optimiser, j'ai juste besoin de pouvoir réutiliser la même table jointe au lieu de rejoindre 3 tables lorsqu'une seule est nécessaire.
Mon exemple actuel ...
$args = array(
'meta_query' => array(
'relation' => 'AND',
array(
'key' => 'abc_type',
'value' => array('puppy', 'kitten'),
'compare' => 'IN',
),
array(
'relation' => 'OR',
array(
'relation' => 'AND',
array(
'key' => 'abc_type',
'value' => 'puppy',
'compare' => '=',
),
array(
'key' => 'abc_color',
'value' => 'pink',
'compare' => '=',
),
),
array(
'relation' => 'AND',
array(
'key' => 'abc_type',
'value' => 'kitten',
'compare' => '=',
),
array(
'key' => 'abc_size',
'value' => 'large',
'compare' => '=',
),
),
),
)
);
get_posts($args);
ce qui se traduit essentiellement par ceci en SQL simple ...
SELECT posts.* FROM posts
INNER JOIN postmeta ON ( posts.ID = postmeta.post_id )
INNER JOIN postmeta AS mt1 ON ( posts.ID = mt1.post_id )
INNER JOIN postmeta AS mt2 ON ( posts.ID = mt2.post_id )
INNER JOIN postmeta AS mt3 ON ( posts.ID = mt3.post_id )
WHERE 1=1
AND
(
( postmeta.meta_key = 'abc_type' AND postmeta.meta_value IN ('puppy','kitten') )
AND
(
(
( mt1.meta_key = 'abc_type' AND mt1.meta_value = 'puppy' )
AND
( mt2.meta_key = 'abc_color' AND mt2.meta_value > 'pink' )
)
OR
(
( mt3.meta_key = 'abc_type' AND mt3.meta_value = 'kitten' )
AND
( mt4.meta_key = 'abc_size' AND mt4.meta_value = 'large' )
)
)
) AND posts.post_type = 'abc_mypost' AND ((posts.post_status = 'publish'))
GROUP BY posts.ID ORDER BY posts.post_title ASC;
Cependant, cela ajoute 2 jointures supplémentaires pour le champ méta personnalisé abc_type
et en tant que telles, les performances ont pris un grand coup. Existe-t-il un moyen de pouvoir référencer le même alias pour plusieurs arguments meta_query? Fondamentalement, mt1
et mt3
sont totalement inutiles, je devrais simplement pouvoir référencer le premier postmeta
tableau utilisé avec le premier ( postmeta.meta_key = 'abc_type' AND postmeta.meta_value IN ('puppy','kitten') )
. Ou du moins, si je peux définir un alias personnalisé sur chacun d'eux, je pourrais y faire référence.
Une requête plus optimale serait ...
SELECT posts.* FROM posts
INNER JOIN postmeta ON ( posts.ID = postmeta.post_id )
INNER JOIN postmeta AS mt1 ON ( posts.ID = mt1.post_id )
INNER JOIN postmeta AS mt2 ON ( posts.ID = mt2.post_id )
WHERE 1=1
AND
(
( postmeta.meta_key = 'abc_type' AND postmeta.meta_value IN ('puppy','kitten') )
AND
(
(
( postmeta.meta_key = 'abc_type' AND postmeta.meta_value = 'puppy' )
AND
( mt1.meta_key = 'abc_color' AND mt1.meta_value > 'pink' )
)
OR
(
( postmeta.meta_key = 'abc_type' AND postmeta.meta_value = 'kitten' )
AND
( mt2.meta_key = 'abc_color' AND mt2.meta_value = 'green' )
)
)
) AND posts.post_type = 'abc_mypost' AND ((posts.post_status = 'publish'))
GROUP BY posts.ID ORDER BY posts.post_title ASC;
Pensées?
la source
get_posts()
.posts_where
filtre pourrait être utile.Réponses:
Jetez un œil au
meta_query_find_compatible_table_alias
filtre défini danswp-includes/class-wp-meta-query.php
. La documentation de ce filtre:Il est probable que la fonction appelante
find_compatible_table_alias
retourne false et donc la requête crée lesmt*
alias. Voici un exemple de code utilisant ce filtre, bien que je plaide personnellement pour quelque chose d'un peu plus facile à comprendre. La modification de requêtes comme celle-ci peut entraîner des tonnes de maux de tête sur la route et il peut ne pas être évident du tout où la requête est gâchée, surtout si vous faites appel à d'autres développeurs à l'avenir. Cela dit...Il en résulte une requête comme
la source
Vous pouvez utiliser les filtres
posts_where
etposts_join
pour modifier la requête. Ce n'est pas très élégant, mais vous devriez pouvoir jouer avec ces deux filtres pour que votre sql soit plus optimisé. C'est une sorte de force brute, mais je ne vois pas de meilleure façon dans la classe WP_Query. Cela ne veut pas dire qu'il n'y en a pas.Il devrait probablement y avoir des vérifications afin de ne pas modifier accidentellement d'autres requêtes. Cela reste un exercice pour le lecteur.
la source
Vous pouvez optimiser votre requête en supprimant la première méta-requête car elle est redondante, comme ceci:
De cette façon, vous n'obtiendrez que l'un
pink puppy
ou l' autrelarge kitten
, comme vous le souhaitez, je crois.En ce qui concerne l'optimisation des requêtes MySQL internes de WordPress, je pense que vous devriez rester à l'écart de cela car vous vous exposeriez à des effets secondaires possibles. Vous feriez mieux de compter sur le fait que les requêtes sont mises en cache et effectuent un traitement PHP supplémentaire sur l'ensemble de données (plus grand). Je crois que cela conduira à de meilleures performances dans l'ensemble car le goulot d'étranglement n'est pas la quantité de données que vous extrayez de la base de données, mais la difficulté avec laquelle elles sont collectées (combien de requêtes). PHP est assez rapide en passant par les tableaux.
Je pense donc qu'une situation comme celle-ci est plus rapide, étant donné que la méta post est mise en cache:
la source
Je ne suis pas vraiment un type de base de données, mais j'en ai joué un à la télévision une fois ...
Cette partie ne serait-elle pas
être mieux remplacé par
Cela pourrait probablement être encore plus simplifié ... avec un alias coincé là au bon endroit afin que vous puissiez utiliser le reste de votre requête.
Juste une pensée...
la source
get_posts()
, donc il n'écrit pas lui-même la requête.