¿Hay alguna manera de establecer un alias en los argumentos meta_query cuando se ejecuta un get_posts()
? Una de mis consultas está funcionando mal. Para optimizar, solo necesito poder reutilizar la misma tabla unida en lugar de unirme en 3 tablas cuando solo se necesita una.
Mi ejemplo actual ...
$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);
que básicamente se traduce a esto en SQL directo ...
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;
Sin embargo, esto está agregando 2 combinaciones adicionales para el metacampo personalizado abc_type
y, como tal, el rendimiento ha tenido un gran éxito. ¿Hay alguna manera de poder hacer referencia al mismo alias para múltiples argumentos meta_query? Básicamente, mt1
y mt3
son totalmente innecesarios, debería poder hacer referencia a la primera postmeta
tabla que se usa con la primera ( postmeta.meta_key = 'abc_type' AND postmeta.meta_value IN ('puppy','kitten') )
. O al menos si puedo establecer un alias personalizado en cada uno de estos, podría hacer referencia a eso.
Una consulta más óptima sería ...
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;
Pensamientos?
fuente
get_posts()
.posts_where
filtro puede ser útil.Respuestas:
Echa un vistazo al
meta_query_find_compatible_table_alias
filtro definido enwp-includes/class-wp-meta-query.php
. La documentación de este filtro:Es probable que la función de llamada,
find_compatible_table_alias
devuelva false y, por lo tanto, la consulta crea losmt*
alias. Aquí hay un código de muestra que usa este filtro, aunque personalmente recomendaría algo que sea un poco más fácil de entender. Modificar consultas como esta puede generar toneladas de dolores de cabeza en el futuro y puede que no sea evidente en absoluto dónde la consulta se desordenará, especialmente si trae otros desarrolladores en el futuro. Dicho eso ...Esto da como resultado una consulta como
fuente
Puede usar los filtros
posts_where
yposts_join
para modificar la consulta. No es muy elegante, pero debería poder meterse con estos dos filtros para que su sql esté más optimizado. Es una especie de fuerza bruta, pero no puedo ver una mejor manera en la clase WP_Query. Sin embargo, eso no quiere decir que no haya.Probablemente debería haber algunas comprobaciones allí para que no esté modificando accidentalmente otras consultas. Eso queda como ejercicio para el lector.
fuente
Puede optimizar su consulta eliminando la primera meta consulta ya que es redundante, de esta manera:
De esta manera solo obtendrás uno
pink puppy
olarge kitten
, según tu intención, creo.En cuanto a la optimización de las consultas internas de MySQL de WordPress, creo que debe mantenerse alejado de eso, ya que se expondría a posibles efectos secundarios. Sería mejor confiar en el hecho de que las consultas se almacenan en caché y realizan más procesamiento PHP en el conjunto de datos (más grande). Creo que esto conducirá a un mejor rendimiento general, ya que el cuello de botella no es la cantidad de datos que extrae de la base de datos, sino la dificultad con la que se recopila (cuántas consultas). PHP es bastante rápido como viene a través de matrices
Entonces, creo que una situación como esta es más rápida, teniendo en cuenta que el meta de la publicación se almacena en caché:
fuente
Realmente no soy un tipo de base de datos, pero jugué uno en la televisión una vez ...
¿No sería esta parte
ser mejor reemplazado con
Eso probablemente podría simplificarse aún más ... con algunos alias pegados allí en el lugar adecuado para que pueda usar el resto de su consulta.
Solo un pensamiento...
fuente
get_posts()
, por lo que no está escribiendo la consulta él mismo.