¿Es posible ordenar varias meta_keys cuando se utiliza meta_value_num?

4

Leer a través de order & Para ordenar la documentación , no tengo claro si hay algún tipo de soporte para realizar pedidos basado en múltiples valores de meta_key .

Obviamente, al usar meta_query puedo devolver publicaciones basadas en varios pares clave-valor, pero quiero poder controlar el orden en que estos resultados se devuelven en base a múltiples meta_keys .

Por ejemplo, tengo páginas que tienen múltiples categorías y cada categoría tiene un rango numérico. Si un usuario está buscando páginas que se encuentran en una de tres categorías diferentes, puedo devolver todas las publicaciones necesarias con lo siguiente:

$query = array(
  'order' => 'DESC',
  'orderby' => 'meta_value_num',
  'meta_query' => array(
    'relation' => 'OR',
    array( 'key' => 'cat1', 'type' => 'numeric' ),
    array( 'key' => 'cat2', 'type' => 'numeric' ),
    array( 'key' => 'cat3', 'type' => 'numeric' )
  );
);

Sin embargo, una vez que se devuelven, me gustaría que se ordenen en función del valor numérico más alto en cualquiera de las categorías en las que se devolvieron los resultados. En otras palabras, las publicaciones con un valor 9 en cat1 aparecerán en el mismo orden que las publicaciones con un valor 9 en cat3 .

Mirando esta respuesta parece que un meta_key ni siquiera es necesario para 'orderby' => 'meta_value_num' , pero eso no coincide con la documentación de meta_value , que está mucho más documentada que meta_value_num ... Cualquier aclaración sería útil. Gracias!

    
pregunta Dan 16.01.2013 - 21:00

2 respuestas

1

Es posible que desee revisar las mejoras de la consulta en WP 4.2 para "orderby" y "meta_query". Los detalles están en enlace .

Intenta nombrar tus cláusulas de meta_query, luego ordena por ellas.

El siguiente código no está probado:

$query = array(
  'order' => 'DESC',
  'meta_query' => array(
    'relation' => 'OR',
    'cat1-clause' => array( 'key' => 'cat1', 'type' => 'numeric' ),
    'cat2-clause' => array( 'key' => 'cat2', 'type' => 'numeric' ),
    'cat3-clause' => array( 'key' => 'cat3', 'type' => 'numeric' )
  );
  'orderby' => array(
    'cat1-clause' => 'ASC',
    'cat2-clause' => 'ASC',
    'cat3-clause' => 'ASC',
  ),
);
    
respondido por el Pim Schaaf 24.06.2016 - 06:46
0

Si observa el método get_posts de WP_Query, es fácil depurar el sql generando la variable pasada al filtro posts_request .

// Debug the WP_Query sql
add_filter( 'posts_request', function( $sql ) {
  echo "<pre>";
  var_dump( $sql );
  echo "</pre>";
  return $sql;
} );

El resultado debería verse así:

string(426) "SELECT SQL_CALC_FOUND_ROWS  wp_posts.* FROM wp_posts  INNER JOIN wp_postmeta ON ( wp_posts.ID = wp_postmeta.post_id ) WHERE 1=1  AND wp_posts.post_type = 'post' AND (wp_posts.post_status = 'publish' OR wp_posts.post_status = 'private') AND (
  wp_postmeta.meta_key = 'cat1'
  OR
  wp_postmeta.meta_key = 'cat2'
  OR
  wp_postmeta.meta_key = 'cat3'
) GROUP BY wp_posts.ID ORDER BY wp_postmeta.meta_value+0 DESC LIMIT 0, 10"

La consulta puede parecer correcta al principio, pero no lo es. Utiliza el meta_value de la primera fila en la unión interna para la cláusula ORDER BY . En este caso eso es 'cat1' . Para cambiar este comportamiento, podemos usar el gancho posts_orderby para modificar la declaración ORDER BY y usar la función MAX mysql para que use el valor más alto de todos los valores meta en lugar de solo la primera fila.

// Filter to alter the orderby sql
function nvdGMCWh_alter_posts_orderby( $sql ) {
  return "MAX( $wpdb->postmeta.meta_value+0 ) DESC";
} // - alter_posts_orderby
// Register the filter
add_filter( 'posts_orderby', 'nvdGMCWh_alter_posts_orderby' );

// The WP_Query
$res = new WP_Query;
$args = [
  'order' => 'DESC',
  'orderby' => 'meta_value_num',
  'meta_query' => [
    'relation' => 'OR',
    ['key' => 'cat1', 'type' => 'numeric'],
    ['key' => 'cat2', 'type' => 'numeric'],
    ['key' => 'cat3', 'type' => 'numeric'],
  ],
]; // - $args
// Execute the query and get the results
$result = $res->query( $args );
// Clean up the filter so it won't affect later queries
remove_filter( 'posts_orderby', 'nvdGMCWh_alter_posts_orderby' );
// Loop through the results
foreach ( $result as $post ) {
  // ... code here
} // - foreach
    
respondido por el forsvunnet 19.04.2015 - 13:49

Lea otras preguntas en las etiquetas