WP_Query - Ordenar resultados por valor meta
He revisado y no he encontrado una respuesta que funcione hasta ahora. Tengo una WP_Query con los siguientes argumentos:
$args = array(
'post_status' => 'publish',
'post_type' => 'listing',
'meta_key' => 'client_feedback_score',
'orderby' => 'client_feedback_score',
'order' => 'DESC'
);
$query = new WP_Query($args);
Quiero ordenar los resultados por el campo personalizado client_feedback_score
, de menor a mayor. Pero esto no parece funcionar... ¿alguien puede indicarme la dirección correcta?
EDICIÓN (RESUELTO):
Gracias a la respuesta de Milo, aquí está el código que funciona para ordenar por un valor meta numérico:
$args = array(
'post_status' => 'publish',
'post_type' => 'listing',
'meta_key' => 'client_feedback_score',
'orderby' => 'meta_value_num',
'order' => 'DESC'
);

El parámetro orderby
debe ser meta_value_num
o meta_value
, no el nombre de la clave. Consulta los parámetros orderby de WP_Query.

¡Gracias! ¡Eres mi salvador! En ningún lugar de WPCodex se menciona 'meta_value_num'.

Pequeña nota: si la clave meta_key
no existe aún para la entrada, esta será ignorada.

¿Es meta_value_num
un meta personalizado de posts que puedes asignar a tipos de posts? Necesito poder editar este valor por cada post.

@RobBenz Mira Campos Personalizados para aprender sobre meta de posts.

gracias, estoy familiarizado con los meta personalizados de posts. Quiero añadir un meta box a productos de WC, llamado search_order
o algo similar. Así cuando se muestren los resultados de búsqueda: pueda tener la capacidad de controlar el orden en que se muestran. ¿Debería llamar al meta personalizado que estoy añadiendo meta_value_num

o ¿meta_value_num
simplemente toma el valor de cualquier 'meta_key' => 'search_order' basado en el post?

@RobBenz meta_value_num
le está indicando a WP que ordene los resultados por un valor meta numérico. No es el nombre de la clave.

¿cómo puedo cambiar meta_value_num
para que un post en particular "clasifique" más arriba en los resultados de búsqueda?

@RobBenz Probablemente deberías iniciar una nueva pregunta sobre este tema. Paso 1 Asigna el valor que desees a tu clave meta, llamémosla my_meta_key
, para cada publicación para generar el orden que prefieras. Paso 2 Configuras meta_key
en tu consulta como my_meta_key
. Esto le indica a WordPress que consulte las publicaciones que tienen esa clave. Paso 3 Establece orderby
en tu consulta como meta_value_num
. Esto le dice a WordPress que no solo consulte publicaciones con my_meta_key
, sino que también las ordene numéricamente por esa clave. Ese argumento de consulta es el único lugar donde verás o usarás meta_value_num
.

@adamj ¿hay alguna solución alternativa para esto? Necesito ordenar todas las publicaciones, independientemente de que exista meta_key para la publicación o no.

Si tu valor meta no es numérico, por ejemplo si es un valor de fecha; entonces puedes añadir el parámetro meta_type => DATE
.
Los valores posibles son: 'NUMERIC', 'BINARY', 'CHAR', 'DATE', 'DATETIME', 'DECIMAL', 'SIGNED', 'TIME', 'UNSIGNED'
.
La consulta con el tipo meta será así:
$args = array(
'post_status' => 'publish',
'post_type' => 'listing',
'meta_key' => 'client_feedback_score',
'orderby' => 'meta_value_num',
'meta_type' => 'DATE',
'order' => 'DESC'
);

Para abordar el punto planteado por @adamj en la respuesta aceptada
si el meta_key no existe aún para el post, el post será ignorado.
Aquí hay una solución que incluirá incluso los posts que no tengan un valor de client_feedback_score
. Puedes configurar una consulta simple que liste todos los posts. Luego hacer manualmente un left join con la tabla postmeta
donde el meta_value
sea client_feedback_score
. Finalmente ordenarlos con una cláusula orderby
.
$args = array(
'post_status' => 'publish',
'post_type' => 'listing',
);
add_filter('posts_clauses','post_meta_sort',10,1);
function post_meta_sort( $sql_clauses ) {
global $wpdb;
remove_filter( 'posts_clauses', 'post_meta_sort' ); // Evita que esta función se ejecute en otras consultas.
$sql_clauses['join'] .= "LEFT JOIN $wpdb->postmeta AS sort_score_postmeta ON $wpdb->posts.ID = sort_score_postmeta.post_id
AND sort_score_postmeta.meta_key = 'client_feedback_score'";
$sql_clauses['orderby'] = 'sort_score_postmeta.meta_value+0 DESC';
return $sql_clauses;
}
$query = new WP_Query($args);
