Obtener publicación con múltiples meta keys y valores

2 sept 2016, 09:12:26
Vistas: 38.9K
Votos: 11

Estoy tratando de obtener una publicación basada en las siguientes meta keys.

  • post_code con 432C
  • location con XYZ Ambos pertenecen a un CPT. Estoy tratando de obtener la Publicación con ambos meta_values.

No quiero una relación OR, quiero una relación AND. He probado varios objetos WP_Query y todavía no he encontrado una solución después de horas de búsqueda.

2
Comentarios

¿Qué código WP_Query real has probado?

RRikesh RRikesh
2 sept 2016 09:26:08

$args = array( 'post_type' => 'courses', 'meta_query' => array( array( 'key' => 'post_code', 'value' => '432C', ), array( 'key' => 'location', 'value' => 'XYZ', ), ), ); $query = new WP_Query( $args );

Sheraz Ahmed Sheraz Ahmed
2 sept 2016 09:34:15
Todas las respuestas a la pregunta 6
3
17

Esto debería funcionar. La relación por defecto es AND (Y) así que no será necesario especificarla.

$args = array(
    'post_type'  => 'wpse_cpt',
    'meta_query' => array(
        array(
            'key'     => 'post_code',
            'value'   => '432C',
        ),
        array(
            'key'     => 'location',
            'value'   => 'XYZ',
        ),
    ),
);
$query = new WP_Query( $args );
2 sept 2016 09:31:02
Comentarios

Lo he intentado, pero esto me da demasiada información. Estoy tratando de obtener resultados usando $wpdb... ¿Es posible?

Sheraz Ahmed Sheraz Ahmed
2 sept 2016 09:36:11

Esto devolverá los resultados que describiste en tu pregunta. Así que, o necesitas hacer una consulta más específica, o asegurarte de que tus posts tengan metadatos precisos.

Jeremy Ross Jeremy Ross
2 sept 2016 16:42:10

Y sí, puedes usar $wpdb, pero obtendrás los mismos resultados si usas los mismos criterios. WP_Query es más fácil y seguro.

Jeremy Ross Jeremy Ross
2 sept 2016 16:43:24
0
$args = array(
    'post_type'  => 'wpse_cpt',
    'meta_query' => array(
        'relation' => 'AND' //**** Usa AND u OR según tu cláusula Where requerida
        array(
            'key'     => 'post_code',
            'value'   => '432C',
        ),
        array(
            'key'     => 'location',
            'value'   => 'XYZ',
        ),
    ),
);
$query = new WP_Query( $args );
2 sept 2016 16:23:26
4

Editar de nuevo: Ah, no respondí a la pregunta. Seleccionarías a.* para obtener todas las columnas de los posts con los valores de clave coincidentes, en lugar de seleccionar c.meta_value.

La siguiente consulta SQL/$wpdb seleccionará todos los meta_value%s de un post con post_type de $postType y un valor meta_key de $metaKey. Por lo tanto, selecciona todos los valores diferentes de una meta_key dada (a través de '$metaKey'). La tabla term_relationships es la tabla auxiliar de WordPress para conexiones de relaciones entre tablas. wp_posts es la tabla 'posts' de WordPress, y wp_postmeta es la tabla 'postmeta' de WordPress. (Nota: Si estás usando tablas personalizadas, estos nombres de tabla serían diferentes).

~ Editado para agregar notas de 'haciendo', solicitado por @MikeNGarrett

/* $wpdb es una variable global proporcionada por el 'motor' de WordPress
** para consultar tablas de la base de datos de WordPress.
*/
global $wpdb; 
$postType = 'mycustomposttype';
$metaKey = 'mymetakey';
$query = "
    SELECT c.meta_value 
    FROM wp_posts a 
    LEFT JOIN wp_term_relationships b 
        ON (a.ID = b.object_id) 
    LEFT JOIN wp_postmeta c 
        ON (a.ID = c.post_id) 
    WHERE a.post_type = %s AND c.meta_key = %s";

$metaValues = $wpdb->prepare(query, [$postType, $metaKey]);
$metaValues = $wpdb->get_results($metaValues);

Notas: Solo estoy reutilizando la variable $metaValues. No hay otra razón para escribir los resultados de $metaValues prepare() de nuevo en la variable $metaValues. Sin embargo, debes pasar $metaValues a get_results().

8 may 2019 16:56:16
Comentarios

¡Hola Eric! ¿Puedes proporcionar un poco más de contexto? Especialmente respondiendo "¿Qué hace este código?" y "¿Por qué es la mejor manera de lograr esto?"

MikeNGarrett MikeNGarrett
8 may 2019 17:56:07

@MikeNGarrett, he añadido notas. En realidad, puedes devolver los valores que quieras de cualquiera de esas tres tablas con la consulta. Solo necesitas cambiar de qué tabla estás preguntando/comparando. Mediante a, b, c y . y el nombre de la columna.

Eric Shoberg Eric Shoberg
8 may 2019 22:47:29

@MikeGarrett, "¿Por qué es la mejor manera de lograr esto?". Honestamente, no sé si esta es la 'mejor' manera de lograrlo. Sin embargo, funciona. También me interesaría si alguien encuentra una forma mejor/más rápida. Creo que esta es la forma menos exigente de hacerlo, según mis habilidades y conocimientos actuales en este momento.

Eric Shoberg Eric Shoberg
8 may 2019 23:06:46

¡Gracias! Se ve bien

MikeNGarrett MikeNGarrett
9 may 2019 18:49:27
0

SOLUCIÓN

La solución aceptada a continuación funcionó, sin embargo, quería saber ¿cómo está funcionando?

Así es como funciona:

SELECT * FROM wp_posts p, wp_postmeta m1, wp_postmeta m2
    WHERE p.ID = m1.post_id AND p.ID = m2.post_id
    AND m1.meta_key = 'key1' AND m1.meta_value = 'value1'
    AND m2.meta_key = 'key2' AND m2.meta_value = 'value2'
    AND p.post_type = 'cpt' AND p.post_status = 'published'
15 jul 2017 11:24:51
0

Probé la solución con WP_Query sugerida anteriormente, pero obtuve un resultado vacío. La sugerida por Sheraz Ahmed funciona bien. Aquí está mi propia versión por si sirve de algo:

//base de datos
wp_posts
+---------+--------------------+--------------+
|  ID     | post_title         | post_type    |
+---------+--------------------+--------------+
| 8567    | Introducción a MySQL| talk         |
+---------+--------------------+--------------+
| 8590    | Introducción a PHP | talk         |
+---------+--------------------+--------------+

wp_postmeta
+---------------+------------+----------------+
|  post_id      | meta_key   | meta_value     |
+---------------+------------+----------------+
| 8567          | speaker    | John Doe       |
+---------------+------------+----------------+
| 8567          | year_of    | 2021           |
+---------------+------------+----------------+
| 8590          | speaker    | John Doe       |
+---------------+------------+----------------+
| 8590          | year_of    | 2021           |
+---------------+------------+----------------+


//buscar por speaker y año
$speaker = "John Doe";
$year_of = "2021";

$talks = $wpdb->get_results(  
     $wpdb->prepare( 
         'SELECT post_title, meta_value AS speaker 
         FROM '.$wpdb->prefix.'posts AS pt, '.$wpdb->prefix.'postmeta AS pm 
         WHERE post_type = %s AND pm.post_id = pt.id AND ( meta_key = %s AND meta_value = %s ) 
         AND post_id IN ( SELECT post_id FROM nm_postmeta WHERE meta_key = %s AND meta_value = %s )',
         array( 'talk', 
                'speaker', 
                $speaker, 
                'year_of', 
                $year_of )
    )
);
                
foreach ( $talks as $talk ) {
    echo "<p>".$talk->speaker.': '.$talk_homily->post_title."</p>";
}

John Doe: Introducción a MySQL

John Doe: Introducción a PHP

12 sept 2021 22:48:35
3
-1

Probé los siguientes parámetros de objeto

array(
            'key' => 'post_code',
            'value' =>'432C',
            'compare' => '='
        ),
        array(
            'relation' =>'AND',
             array(

            'key' => 'location',
            'value' => 'XYZ',
             'compare' => '=',

          ),
        )
2 sept 2016 09:28:41
Comentarios

Sería genial si pudieras explicar el código y cómo resuelve el problema.

bravokeyl bravokeyl
2 sept 2016 09:33:18

Ya lo he explicado, por favor prueba estos parámetros usando estos parámetros, automáticamente resolverá el problema

Manthan Dave Manthan Dave
2 sept 2016 09:34:57

Deberías explicar por qué ese código funcionará.

RRikesh RRikesh
2 sept 2016 09:37:50