Ordenar por valor meta pero incluir publicaciones que no tienen uno

37

He estado modificando la búsqueda de WP incorporada utilizando el pre_get_postsfiltro, lo que permite al usuario ordenar las publicaciones (incluido un montón de tipos de publicaciones personalizadas) por diferentes campos.

Sin embargo, el problema que tengo es que cuando le digo a WP que ordene por un valor meta, excluirá todas las publicaciones que no tengan ese valor meta establecido. Esto hace que cambie la cantidad de resultados si cambia la ordenación de "Precio" a "Fecha" porque "Publicaciones" no tienen "Precio" establecido, pero sí "Elementos".

Esto no es lo que quiero, así que me gustaría saber si hay una manera de incluir TODAS las publicaciones, incluso aquellas que carecen del metavalor en el que estoy clasificando, y colocar las que no tienen el último valor.

Sé cómo ordenar en más de un campo, pero eso no ayuda.

Gracias

Parece que no soy el único con esta pregunta: ¿ forma de incluir publicaciones con y sin cierta meta_key en args para wp_query? Pero no hay solución allí.

Actualizar

He intentado la respuesta pero no estoy seguro si entendí correctamente, esto es lo que tengo ahora:

<?php
function my_stuff ($qry) {
    $qry->set('meta_query', array(array(
        'key' => 'item_price', 
        'value' => '', 
        'compare' => 'NOT EXISTS'
    )));

    $qry->set('orderby', 'meta_value date'); # Sorting works with meta_value as well as meta_value_num - I've tried both
    $qry->set('order', 'ASC DESC');
    $qry->set('meta_key', 'item_price');
}

El metavalor es un número (se usa para almacenar un precio como sugiere su nombre)

Actualización 2

He comentado el pedido y todo lo que tengo ahora es esto:

<?php
$qry->set('meta_query', array(array(
    'key' => 'item_price', 
    'value' => '', 
    'compare' => 'NOT EXISTS'
)));

Con este código, la consulta parece devolver todas las publicaciones que no tienen la item_priceclave y ninguna de las publicaciones que la tienen. Es decir, el problema ahora se invierte.

Si agrego el código de pedido también obtengo 0 resultados.

Editar: ... tres años después ... : PI tuvo este problema nuevamente. Intenté todas las respuestas dadas y ninguna funciona. No estoy seguro de por qué algunas personas parecen pensar que funcionan, pero al menos no trabajan para mí.

La solución con la que terminé es usar el save_postfiltro, asegurándome de que todas las publicaciones tengan el campo personalizado en el que deseo ordenar. Es un poco molesto que tenga que hacerlo, pero mientras lo hagas pronto es probable que no tengas problemas.

En este caso, estaba creando un "contador de vistas" en las publicaciones y quería que los usuarios pudieran ordenar las publicaciones más leídas. Una vez más, las publicaciones que nunca se han visto (supongo que es bastante improbable, pero aún así) desaparecieron al ordenar el recuento de vistas. Agregué este bit de código para asegurarme de que todas las publicaciones tengan un recuento de vistas:

add_action('save_post', function ($postId) {
    add_post_meta($postId, '_sleek_view_count', 0, true);
});
powerbuoy
fuente
Por favor muéstranos tu código. Hace que sea más fácil responder.
kaiser
Primero: meta_queryy siempretax_query son una, ya que combinan múltiples matrices. Segundo, como se menciona en mi respuesta, debe usarlo para los números. Es posible que también sea necesario definir realmente la (consulte la entrada de la página -Codex). Por último, no tiene sentido en y dirección. Eso no es posible. El delimitador de espacio solo funciona y no puede indicarle que ordene el primero y el segundo . Para eso está el filtro. array( array() )meta_value_nummeta_value_numWP_QueryorderASC DESCorderbyASCDESCposts_clauses
Kaiser
Y asegúrese de que sus meta_value_numentradas sean números reales . Visto con demasiada frecuencia que alguien dice que es un número, pero de hecho lo guarda como una cadena en la base de datos.
Kaiser
Gracias por su ayuda, lo intentaré y me pondré en contacto con usted. La razón ASC DESCes para que se clasifique en meta_valuein ASCy datein in DESC, por lo que puedo decir, funciona.
powerbuoy
1
@Howdy_McGee eso es correcto. Algunos de mis tipos de publicaciones personalizadas TIENEN este valor establecido. Algunos no lo hacen. Y los tipos de publicación incorporados (como POST y PAGE) no lo hacen. Entonces, cada vez que trato de ordenar en ese campo personalizado, solo se muestran las publicaciones CON el campo personalizado.
powerbuoy

Respuestas:

4

Hay dos posibles soluciones para esto:

1. Todas las publicaciones tienen meta

La mejor solución que he encontrado aquí es dar al resto de las publicaciones / productos un precio de artículo de 0. Puede hacerlo manualmente, o recorrer todas las publicaciones y si el precio está vacío, actualícelo.

Para que esto sea manejable en el futuro, puede conectarse save_posty darles un valor cuando se agreguen por primera vez (solo si está en blanco).

2. Múltiples consultas

Puede ejecutar la primera consulta mientras lo hace y almacenar los ID de las publicaciones devueltas. Luego, podría ejecutar otra consulta para todas las publicaciones y la fecha de pedido, excluyendo los ID devueltos de la primera consulta.

A continuación, puede imprimir los dos resultados por separado y obtendrá los resultados deseados.

Steven Jones
fuente
1
Tres años más tarde y tuve el mismo problema nuevamente: P Tuve que usar el save_postmétodo (he actualizado mi pregunta con el código que usé).
powerbuoy
10

Easy Peasy, recién probado en 2018, actualmente en producción.

$query->set( 'meta_query', array(
    'relation' => 'OR',
    array(
        'key' => 'custom_meta_key', 
        'compare' => 'EXISTS'
    ),
    array(
        'key' => 'custom_meta_key', 
        'compare' => 'NOT EXISTS'
    )
) );
$query->set( 'orderby', 'meta_value title' ); 

Esto verifica todos los elementos con y sin la meta clave, sin ningún valor especificado. La meta consulta proporciona la clave para el pedido de manera confiable. Ha sido probado Sin embargo, no estoy seguro de cómo funcionará cuando la metaconsulta utilice varias claves.

Ejemplo práctico

/**
 * Modifies query before retrieving posts. Sets the 
 * `meta_query` and `orderby` param when no `orderby` 
 * param is set, (default ordering).
 * 
 * @param   WP_Query  $query  The full `WP_Query` object.
 * @return  void
 */
function example_post_ordering( $query ) {

    // if not in wp-admin, 
    // and the query is the main query, 
    // and the query is not a singular query, 
    // and the query does not have an orderby param set...
    // Note: check for post types, etc. here as desired.
    if ( ! is_admin() 
    && $query->is_main_query() 
    && ! $query->is_singular() 
    && empty( $query->get( 'orderby' ) ) ) {

        // Setting just `meta_key` is not sufficient, as this 
        // will ignore posts that do not yet, or never will have 
        // a value for the specified key. This meta query will 
        // register the `meta_key` for ordering, but will not 
        // ignore those posts without a value for this key.
        $query->set( 'meta_query', array(
            'relation' => 'OR',
            array(
                'key' => 'custom_meta_key', 
                'compare' => 'EXISTS'
            ),
            array(
                'key' => 'custom_meta_key', 
                'compare' => 'NOT EXISTS'
            )
        ) );

        // Order by the meta value, then by the title if multiple 
        // posts share the same value for the provided meta key.
        // Use `meta_value_num` if the meta values are numeric.
        $query->set( 'orderby', 'meta_value title' );
    }

}

add_action( 'pre_get_posts', 'example_post_ordering', 10 );

Esto ordenará las publicaciones de manera custom_meta_keypredeterminada y no ignorará las publicaciones sin un valor para esa clave.

noahmason
fuente
Solo de leer el código, todo lo que parece hacer es obtener publicaciones que tienen custom_meta_keyy recibir publicaciones que no tienen custom_meta_key. Siéntase libre de incluir un ejemplo de trabajo real con la clasificación.
powerbuoy
1
Tiene razón, eso es todo lo que está haciendo, pero la línea a continuación es responsable de ordenar por meta_value (de la meta clave que se está consultando). $query->set( 'orderby', 'meta_value title' );(Ordenar por metavalor, luego por título cuando varias publicaciones tengan el mismo valor para la metaclave). Esto debe hacerse en el pre_get_postsgancho, utilizando la $queryvariable pasada en . Tenga en cuenta que la pregunta que se hizo fue cómo ordenar por metavalor, sin ignorar las publicaciones que no tienen un valor para esa metaclave.
noahmason
@powerbuoy Ver ejemplo práctico actualizado
noahmason
Bien, lo intentaré la próxima vez que me enfrente a este problema.
powerbuoy
1
Me funcionó en una get_posts()llamada personalizada para empujar publicaciones con _featuredmeta a la parte superior, luego ordenar por fecha después de eso. ¡Gracias!
natebeaty
8

Este método devolverá todas las publicaciones, incluidas aquellas con y sin la solicitada meta_key, pero hará cosas extrañas al realizar el pedido.

add_action('pre_get_posts', 'my_stuff');
function my_stuff ($qry) {
    $qry->set(
        'meta_query',
        array(
            'relation' => 'OR', # Matches to this meta_query should be added to those matching the 'meta_key' query
            array(
                'key' => 'item_price', 
                'value' => 'bug #23268', 
                'compare' => 'NOT EXISTS'
            )
        )
    );

    $qry->set('orderby', 'meta_value date'); # Sorting works with meta_value as well as meta_value_num - I've tried both
    $qry->set('order', 'ASC DESC');
    $qry->set('meta_key', 'item_price');
}

Encontré esto jugando con todas las diferentes respuestas a esta pregunta y analizando el SQL generado a través de prueba y error. Parece que la configuración de array('meta_query' => array('relation' => 'OR'))un resultado apropiado en LEFT JOINlugar de INNER JOINeso es necesario para incluir publicaciones que faltan los metadatos. Especificar el NOT EXISTSevita que la WHEREcláusula filtre las publicaciones que carecen del metacampo. Para este particular WP_Query, el SQL generado es (sangría / nuevas líneas agregadas):

SELECT SQL_CALC_FOUND_ROWS
    wp_posts.ID
    FROM wp_posts
    INNER JOIN wp_term_relationships ON (wp_posts.ID = wp_term_relationships.object_id)
    INNER JOIN wp_postmeta ON wp_posts.ID = wp_postmeta.post_id
    LEFT JOIN wp_postmeta AS mt1 ON (wp_posts.ID = mt1.post_id AND mt1.meta_key = 'item_price')
    WHERE 1=1
    AND ( wp_term_relationships.term_taxonomy_id IN (2) )
    AND wp_posts.post_type = 'post'
    AND (wp_posts.post_status = 'publish'
        OR wp_posts.post_status = 'private')
    AND (wp_postmeta.meta_key = 'item_price'
        -- Oh look, here we give SQL permission to choose a random
        -- row from wp_postmeta when this particular post is missing
        -- 'item_price':
        OR  mt1.post_id IS NULL )
    GROUP BY wp_posts.ID
    ORDER BY wp_postmeta.meta_value,wp_posts.post_date DESC
    LIMIT 0, 10

El resultado es una lista de todas las publicaciones con meta_value item_pricey aquellas que faltan item_price. Todos los mensajes con item_priceque se ordenará correctamente respecto a la otra, pero los mensajes que faltan item_priceusará parte aleatoria otro valor meta (por ejemplo, _edit_lastque parece ser 1muy a menudo en mi base de datos o alguna otra metadatos wordpress interno que es completamente arbitraria) por su wp_postmeta.meta_valueen la ORDER BYcláusula Entonces, si bien este método está cerca y puede parecer que funciona para ciertos datos, está roto. Entonces, todo lo que puedo decir es que si sus item_pricevalores no entran en conflicto con los metacampos aleatorios que MySQL elige para las publicaciones que faltan item_price, esto podría funcionar bien para usted. Si todo lo que necesitas es una garantía de que tus publicaciones conitem_priceestán correctamente ordenados entre sí sin tener en cuenta el orden de otras publicaciones, puede estar bien. Pero creo que esto es solo una deficiencia en wordpress. Corríjame, espero estar equivocado y hay una manera de abordar esto ;-).

Parece que para INNER JOIN wp_postmetaMySQL está eligiendo una fila aleatoria entre varias postmetafilas asociadas con la publicación cuando meta_keyfalta en la publicación dada. Desde una perspectiva SQL, necesitamos descubrir cómo decirle a WordPress que salga ORDER BY mt1.meta_value. Esta columna es correcta NULLcuando meta_keyfalta nuestra solicitud , a diferencia de wp_postmeta.meta_value. Si pudiéramos hacer eso, SQL ordenaría estas NULL(entradas faltantes) antes que cualquier otro valor, dándonos un orden bien definido: primero vienen todas las publicaciones que faltan en el campo postmeta en particular, luego vienen las publicaciones que tienen el campo. Pero ese es todo el problema: 'orderby' => 'meta_value'solo se puede referir 'meta_key' => 'item_price' y lo sin alias wp_postmetasiempre es un, en INNER JOINlugar de siempre LEFT JOIN, un significado wp_postmeta.meta_valuey wp_postmeta.meta_keypuedenunca se NULL.

Así que supongo que tengo que decir que esto no es posible con WordPress incorporado, WP_Queryya que ahora está documentado (en WordPress-3.9.1). Molestia. Entonces, si realmente necesita que esto funcione correctamente, es probable que necesite conectarse a WordPress en otro lugar y modificar el SQL generado directamente .

binki
fuente
¡Parece muy prometedor! Lo intentaré la próxima vez que tenga este problema. Me gustaría darle la respuesta en este momento, pero preferiría confirmar que funciona para mí primero.
powerbuoy
Esto evitó que todo apareciera por mí. Nada se mostró después de implementar esto.
Jake
@Jake Sí, lo mismo aquí. Tuve este problema nuevamente hoy y probé esto. Devuelve 0 resultados.
Powerbuoy
¿Qué versión de wordpress están usando? Creo que esta publicación describe cómo usar una API interna no documentada que no es compatible con wordpress y, por lo tanto, probablemente solo funcione si está en wordpress-3.9.1 o no hay muchas versiones más allá de eso.
binki
2

Creo que tengo una solución.

Puede usar dos meta_keys, uno que tienen todas las publicaciones (like "_thumbnail_id"), y el meta_keyque desea usar como filtro.

Entonces tus argumentos:

$qry->set(
    'meta_query',
    array(
        'relation' => 'OR',
        array(
            'key' => 'item_price', 
            'value' => '', 
            'compare' => 'EXISTS'
        ),
        array(
            'key' => 'item_price', 
            'value' => '', 
            'compare' => 'EXISTS'
        )
    )
);

$qry->set('orderby', 'meta_value date'); # Sorting works with meta_value as well as meta_value_num - I've tried both
$qry->set('order', 'ASC DESC');
$qry->set('meta_key', 'item_price');
Rafael M31
fuente
1
El problema aquí es la comparación de cadenas vacías, elimínela y funciona 'value' => '', también, la segunda comparación debería ser NOT EXISTSy no se requiere la última instrucción establecida
asiente con la cabeza
2

El problema que tienen todos aquí tiene que ver con el orden de las metaconsultas. Para ordenar correctamente, deberá colocar la consulta "NO EXISTE" antes de la consulta "EXISTA".

La razón de esto es porque WordPress usa el meta_valor de la última declaración "LEFT JOIN" en la cláusula "ORDER BY".

Por ejemplo:

$pageQuery = new WP_Query([
    'meta_query' => [
        'relation' => 'OR',
        ['key' => 'item_price', 'compare' => 'NOT EXISTS'], // this comes first!
        ['key' => 'item_price', 'compare' => 'EXISTS'],
    ],
    'order' => 'DESC',
    'orderby' => 'meta_value_num',
    'post_status' => 'publish',
    'post_type' => 'page',
    'posts_per_page' => 10,
]);
Paul
fuente
1

Si es adecuado, puede agregar un metavalor predeterminado cada vez que se guarda o actualiza una publicación, si el metavalor no existe.

function addDefaultMetaValue($post_id) {
    add_post_meta($post_id, 'item_price', 0, true);
}
add_action('save_post', 'addDefaultMetaValue');

Si está utilizando un tipo de publicación personalizado, reemplácelo add_action('save_post', 'addDefaultMetaValue');por add_action('save_post_{post_type}', 'addDefaultMetaValue');ej.add_action('save_post_product', 'addDefaultMetaValue');

rjpedrosa
fuente
1

Tuve el problema por mí mismo para los meta valores numéricos y señalé que el orden de la consulta también es importante. Para mí, la NOT EXISTSconsulta tiene que ser la primera.

Ejemplo:

$query->set( 'orderby', 'meta_value_num' );
$query->set( 'meta_query', [
    'relation' => 'OR',
    [ 'key' => 'your_meta_name', 'compare' => 'NOT EXISTS' ],
    [
        'key' => 'your_meta_name',
        'compare' => 'EXISTS',
    ],
] );

También es importante para obtener la dirección correcta para los valores numéricos el general ’orderby’a configurar ’meta_value_num’. De lo contrario, tendrá resultados extraños para los valores numéricos, por ejemplo:

1, 2, 20, 21, 3, 4, 5 ...

En lugar de:

1, 2, 3, 4, 5 ... 20, 21

KittMedia
fuente
1

También encontré un problema similar y la siguiente solución me ayudó:

$args = array(
'post_type' => 'kosh_products',
'posts_per_page' => -1,
'meta_query' => array(
    'relation' => 'OR',
    'category_sort_order' => array(
        'key' => '_sort_order',
        'compare' => 'EXISTS'
    ),
    'category_sort_order_not_exists' => array(
        'key' => '_sort_order',
        'compare' => 'NOT EXISTS'
    ), 
),
'orderby' => array( 
    'category_sort_order' => 'ASC',
    'date' => 'ASC'
));
$query = new WP_Query( $args );

Encontré una descripción en WordPress Codex con el título " 'orderby' con múltiples 'meta_key's ": https://codex.wordpress.org/Class_Reference/WP_Query#Order_.26_Orderby_Parameters ingrese la descripción de la imagen aquí

Ilya Kogan
fuente
0

Hay un posible orderbyvalor de meta_valueeso.

$query = new WP_Query( array ( 
    'meta_key'   => 'your_keys_name',
    'orderby'    => 'meta_value',
    'order'      => 'DESC',
    'meta_query' => array( array(
         'key'     => 'your_meta_key',
         'value'   => '',
         'compare' => 'NOT EXISTS',
         // 'type'    => 'CHAR',
    ) )
) );

Si obtuvo valores numéricos, simplemente use meta_value_numen su lugar.

Descargo de responsabilidad: esto no se ha probado, pero debería funcionar. El punto es que necesita especificar sus valores meta_keyy key. De lo contrario, no se puede comparar con valores no existentes, lo que debería permitir consultar ambos tipos de publicaciones. Es una especie de hack-ish, pero mientras funcione ...

emperador
fuente
Gracias por su respuesta, revise mi pregunta actualizada, no estoy seguro de haberlo entendido correctamente.
powerbuoy
Todavía no he hecho que esto funcione, así que si tienes una solución, me encantaría saber qué estoy haciendo mal. Además, establezco una recompensa en SO si desea reclamarlo: stackoverflow.com/questions/17016770/…
powerbuoy
1
Dos cosas. 'your_keys_name'y 'your_meta_key'ambos deben ser la misma cadena en lugar de distintos, de lo contrario, parece que has entendido mal la pregunta. En segundo lugar, probé esto en mi configuración local y excluye cualquier publicación donde exista la clave (a través de meta_query) y excluye cualquier publicación donde falta la clave (a través meta_key), lo que no muestra ninguna publicación. Sin embargo, esta respuesta es un paso hacia algo que las palabras al menos ;-).
binki
1
Oh, curiosamente, esta respuesta funciona si sólo se agrega 'relation' => 'OR'a meta_query. Cosas locas o_o.
binki
@binki Solo presenta una edición a mi pregunta y cambie los bits que cree que deberían cambiarse. Este es un sitio impulsado por la comunidad :)
kaiser
0

Creo que lo que @kaiser intentaba hacer era decirle a la consulta que devolviera todas las publicaciones que tienen esa metaclave aplicando una especie de ficticio donde la condición de no filtrar cualquiera de esos mensajes. Entonces, si conoce todos los valores que pueden tomar sus campos personalizados son x, y, z, podría decir "WHERE meta_key IN (x, y, z) " pero la idea es que puede evitar ese problema al decir "= (' ') :

$query = new WP_Query( array ( 
    'orderby'    => 'meta_value_num',
    'order'      => 'DESC',
    'meta_query' => array( array(
         'key'     => 'item_price',
         'value'   => '',
         'compare' => '!=',
    ) )
) );

Tampoco se ha probado, pero parece que vale la pena intentarlo :-).

Jon
fuente
1
Realmente no puedo probar esto en este momento, pero estoy bastante seguro de que solo devolverá publicaciones donde item_price esté configurado y no ''.
powerbuoy
0

Terminé evitando esto con un poco de un truco (en mi humilde opinión), pero hizo el trabajo para mí en mi caso.

Puedes conectar los filtros posts_join_paged y posts_orderby para actualizar las cadenas de unión y orden. Esto le permitirá ordenar por lo que quiera siempre y cuando se una primero, en lugar de WP_Query, suponiendo que el campo debe existir para esa publicación en particular. A continuación, puede retirar el meta_key, orderbyy `orden de sus argumentos WP_Query.

A continuación se muestra un ejemplo. En la parte superior de cada función, tuve que escapar para ciertos casos, ya que agregará esto a todo lo que use WP_Query. Es posible que deba modificarlo para que se ajuste a sus necesidades particulares.

Lamentablemente falta documentación sobre estos dos filtros, así que ... ¡buena suerte! :)

add_filter('posts_join_paged', 'edit_join', 999, 2);
add_filter('posts_orderby', 'edit_orderby', 999, 2);

/**
 * Edit join
 *
 * @param string $join_paged_statement
 * @param WP_Query $wp_query
 * @return string
 */
function edit_join($join_paged_statement, $wp_query)
{
    global $wpdb;
    if (
        !isset($wp_query->query)
        || $wp_query->is_page
        || $wp_query->is_admin
        || (isset($wp_query->query['post_type']) && $wp_query->query['post_type'] != 'my_custom_post_type')
    ) {
        return $join_paged_statement;
    }

    $join_to_add = "
        LEFT JOIN {$wpdb->prefix}postmeta AS my_custom_meta_key
            ON ({$wpdb->prefix}posts.ID = my_custom_meta_key.post_id
                AND my_custom_meta_key.meta_key = 'my_custom_meta_key')
    ";

    // Only add if it's not already in there
    if (strpos($join_paged_statement, $join_to_add) === false) {
        $join_paged_statement = $join_paged_statement . $join_to_add;
    }

    return $join_paged_statement;
}

/** 
 * Edit orderby
 *
 * @param string $orderby_statement
 * @param WP_Query $wp_query
 * @return string
 */
function edit_orderby($orderby_statement, $wp_query)
{
    if (
        !isset($wp_query->query)
        || $wp_query->is_page
        || $wp_query->is_admin
        || (isset($wp_query->query['post_type']) && $wp_query->query['post_type'] != 'my_custom_post_type')
    ) {
        return $orderby_statement;
    }

    $orderby_statement = "my_custom_meta_key.meta_value DESC";

    return $orderby_statement;
}
Patas desaliñadas
fuente
El código funciona Pero el meta_value se maneja como una cadena. Entonces 6 tiene una calificación más alta como 50. ¿Alguna modificación posible para tratarlos como números?
Drivingralle
@Drivingralle cast(my_custom_meta_key.meta_value as unsigned) DESCdebe hacer el truco ...
tfrommen
1
Gracias @tfrommen. $orderby_statement = "cast(my_custom_meta_key.meta_value as unsigned) DESC";Funciona genial.
Drivingralle
0

Esta solución funcionó para mí:

add_action( 'pre_get_posts', 'orden_portfolio' );
function orden_portfolio( $query ) {

    if( ! is_admin() ) {

        $query->set( 'orderby', 'meta_value_num' );
        $query->set( 'order', 'ASC' );
        $query->set( 'meta_query', [
            'relation' => 'OR',
            [ 
                'key' => 'ce_orden', 
                'compare' => 'NOT EXISTS' ],
            [
                'key' => 'ce_orden',
                'compare' => 'EXISTS',
            ],
        ] );

        return $query;

    }

}

Sin embargo, esta solución muestra primero los registros con meta_value nulo. Esta otra solución muestra el orden ASC y los valores nulos al final:

function custom_join($join) {
    global $wpdb;

    if( ! is_admin() ) {
        $join .= $wpdb->prepare(
        ' LEFT JOIN ' . $wpdb->postmeta . ' cpm ON cpm.post_id = ' . $wpdb->posts . '.ID AND cpm.meta_key = %s'
        , 'ce_orden' );
    }

    return $join;
}

add_filter('posts_join','custom_join');

function custom_orderby($orderby_statement){
    global $wpdb;

    if ( ! is_admin() ) {
        $orderby_statement = "CAST( COALESCE(cpm.meta_value,99999) as SIGNED INTEGER) ASC";
    }

    return $orderby_statement;
}

add_filter('posts_orderby','custom_orderby', 10, 2 ); 
jpussacq
fuente