Necesito obtener un montón de publicaciones con sus metadatos. Por supuesto, no puede obtener metadatos con una consulta de publicaciones estándar, por lo que generalmente tiene que hacer un get_post_custom()
para cada publicación.
Estoy intentando con una consulta personalizada, como esta:
$results = $wpdb->get_results("
SELECT p.ID,
p.post_title,
pm1.meta_value AS first_field,
pm2.meta_value AS second_field,
pm3.meta_value AS third_field
FROM $wpdb->posts p LEFT JOIN $wpdb->postmeta pm1 ON (
pm1.post_id = p.ID AND
pm1.meta_key = 'first_field_key'
) LEFT JOIN $wpdb->postmeta pm2 ON (
pm2.post_id = p.ID AND
pm2.meta_key = 'second_field_key'
) LEFT JOIN $wpdb->postmeta pm3 ON (
pm3.post_id = p.ID AND
pm3.meta_key = 'third_field_key'
)
WHERE post_status = 'publish'
");
Parece funcionar. Se dispara si usa cualquiera de esos metacampos de una manera que permita múltiples metavalores para él en la misma publicación. No puedo pensar en unirme para hacer eso.
Entonces, pregunta 1: ¿hay una combinación, subconsulta o lo que sea, para incorporar metacampos de valores múltiples?
Pero pregunta 2: ¿Vale la pena? ¿Cuántas postmeta
combinaciones de tablas agrego antes de que sea preferible un enfoque de 2 consultas? Podría tomar todos los datos de publicación en una consulta, luego tomar todos los postmeta relevantes en otra, y combinar el meta con los datos de publicación en un conjunto de resultados en PHP. ¿Acabaría siendo más rápido que una única consulta SQL cada vez más compleja, si eso fuera posible?
Siempre pienso: "Ofrezca la mayor cantidad de trabajo posible a la base de datos". ¡No estoy seguro de esto!
get_posts()
, ¿entoncesget_post_meta()
para cada una de ellas? @MannyFleurmond, es difícil encontrar información concreta sobre el almacenamiento en caché incorporado de WP, pero AFAIK almacenaría cosas en caché por solicitud. La llamada al servidor para capturar estos datos es una llamada AJAX, y no creo que otra cosa esté tomando cosas antes.Respuestas:
La metainformación posterior se almacena automáticamente en la memoria caché para un estándar
WP_Query
(y la consulta principal), a menos que usted le diga específicamente que no lo haga utilizando elupdate_post_meta_cache
parámetro.Por lo tanto, no debe escribir sus propias consultas para esto.
Cómo funciona el metacaching para consultas normales:
Si el
update_post_meta_cache
parámetro aWP_Query
no se establece en falso, luego de recuperar las publicaciones de la base de datos, seupdate_post_caches()
llamará a la función, que a su vez llamaupdate_postmeta_cache()
.La
update_postmeta_cache()
función es un contenedor paraupdate_meta_cache()
, y esencialmente llama a un simpleSELECT
con todos los ID de las publicaciones recuperadas. Esto hará que obtenga todos los postmeta, para todas las publicaciones en la consulta, y guarde esos datos en el caché de objetos (usandowp_cache_add()
).Cuando haces algo como
get_post_custom()
, primero está comprobando el caché de ese objeto. Por lo tanto, no está haciendo consultas adicionales para obtener la meta meta en este momento. Si ha recibido la publicación en unWP_Query
, entonces el meta ya está en la memoria y lo obtiene directamente desde allí.Las ventajas aquí son muchas veces mayores que hacer una consulta compleja, pero la mayor ventaja proviene del uso de la caché de objetos. Si usa una solución de memoria caché persistente como XCache o memcached o APC o algo así, y tiene un complemento que puede vincular su caché de objetos (W3 Total Cache, por ejemplo), entonces todo el caché de objetos se almacena en memoria rápida ya. En este caso, hay cero consultas necesarias para recuperar sus datos; Ya está en la memoria. El almacenamiento en caché de objetos persistente es impresionante en muchos aspectos.
En otras palabras, su consulta es probablemente más lenta que usar una consulta adecuada y una solución simple de memoria persistente. Usa lo normal
WP_Query
. Ahórrate un poco de esfuerzo.Adicional:
update_meta_cache()
es inteligente, por cierto. No recuperará metainformación para publicaciones que ya tienen su metainformación en caché. No obtiene el mismo meta dos veces, básicamente. Súper eficienteAdicional adicional: "Ofrezca la mayor cantidad de trabajo posible a la base de datos" ... No, esta es la web. Se aplican diferentes reglas. En general, siempre desea dar el menor trabajo posible a la base de datos, si es factible. Las bases de datos son lentas o están mal configuradas (si no lo configuró específicamente, puede apostar un buen dinero a que esto es cierto). A menudo se comparten entre muchos sitios y se sobrecargan hasta cierto punto. Por lo general, tiene más servidores web que bases de datos. En general, solo desea obtener los datos que desea de la base de datos de la forma más rápida y sencilla posible, y luego ordenarlos utilizando el código del lado del servidor web. Como principio general, por supuesto, los diferentes casos son todos diferentes.
fuente
Recomendaría una consulta dinámica. Usando tu ejemplo:
fuente
Me he encontrado con un caso en el que también quiero recuperar rápidamente muchas publicaciones con su metainformación asociada. Necesito recuperar las publicaciones de O (2000).
Lo probé usando la sugerencia de Otto: ejecutar WP_Query :: query para todas las publicaciones, y luego recorrer y ejecutar get_post_custom para cada publicación. Esto tomó, en promedio, unos 3 segundos en completarse .
Luego probé la consulta dinámica de Ethan (aunque no me gustaba tener que pedir manualmente cada meta_key que me interesaba). Todavía tenía que recorrer todas las publicaciones recuperadas para deserializar el meta_valor. Esto tomó, en promedio, aproximadamente 1.3 segundos en completarse .
Luego intenté usar la función GROUP_CONCAT y encontré el mejor resultado. Aquí está el código:
Esto tomó un promedio de 0.7 segundos . Eso es aproximadamente una cuarta parte del tiempo de la solución WP get_post_custom () y aproximadamente la mitad de la solución de consulta dinámica.
Tal vez esto sea de interés para alguien.
fuente
Me encontré en una situación en la que necesitaba hacer esta tarea para finalmente crear un documento CSV, terminé trabajando directamente con mysql para hacer esto. Mi código se une a las tablas de publicación y meta para recuperar información de precios de woocommerce, la solución publicada anteriormente requería que usara alias de tabla en el sql para funcionar correctamente.
Sin embargo, tenga en cuenta que woocommerce creó más de 300K filas en mi metatabla, por lo que era muy grande y, por lo tanto, muy lento.
fuente
SIN VERSIÓN SQL:
Obtenga todas las publicaciones y todos sus meta valores (metas) sin SQL:
Digamos que tiene una lista de ID de publicaciones almacenadas como una matriz de ID, algo así como
Ahora no es posible obtener todas las publicaciones y todas las metas en 1 consulta sin usar al menos un poco de SQL, por lo que debemos hacer 2 consultas (todavía solo 2):
1. Obtenga todas las publicaciones (usando WP_Query )
(No olvides llamar
wp_reset_postdata();
si estás haciendo un "ciclo" después;))2. Actualizar meta cache
Para obtener los metadatos, simplemente use el estándar
get_post_meta()
que, como señaló @Otto:primero busca en el caché :)
Nota: Si realmente no necesita otros datos de las publicaciones (como título, contenido, ...) , puede hacer solo 2. :-)
fuente
utilizando la solución trevor y modificándola para que funcione con SQL anidado. Esto no está probado.
fuente
También me encontré con el problema de los metacampos de valores múltiples. El problema es con WordPress en sí. Busque en wp-includes / meta.php. Busque esta línea:
El problema es con la declaración CAST. En una consulta de meta valores, la variable $ meta_type se establece en CHAR. No conozco los detalles sobre cómo CASTing el valor de CHAR afecta la cadena serializada, pero para solucionarlo, puede eliminar la conversión para que el SQL se vea así:
Ahora, a pesar de que eso funciona, estás jugando con las partes internas de WordPress, por lo que otras cosas podrían romperse, y no es una solución permanente, suponiendo que necesites actualizar WordPress.
La forma en que lo arreglé es copiar el SQL generado por WordPress para la meta consulta que quiero y luego escribir PHP para agregar declaraciones AND adicionales para los meta_valores que estoy buscando y usar $ wpdb-> get_results ($ sql ) para el resultado final. Hacky, pero funciona.
fuente
get_meta_sql
filtro que sigue esta línea, por supuesto, sería preferible a hackear el código central.