Preciso receber várias postagens com seus metadados. É claro que você não pode obter metadados com uma consulta de postagens padrão; portanto, você geralmente precisa fazer um get_post_custom()
para cada postagem.
Estou tentando com uma 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. Ele dispara se você usar qualquer um desses meta-campos de uma maneira que permita vários valores-meta na mesma postagem. Não consigo pensar em uma junção para fazer isso.
Então, pergunta 1: existe uma junção, subconsulta ou qualquer outra coisa para trazer metacarpos de valores múltiplos?
Mas pergunta 2: vale a pena? Quantas postmeta
associações de tabela adiciono antes que uma abordagem de 2 consultas se torne preferível? Eu poderia pegar todos os dados de postagem em uma consulta, depois pegar todos os postmeta relevantes em outra e combinar a meta com os dados de postagem em um conjunto de resultados em PHP. Isso acabaria sendo mais rápido que uma única consulta SQL cada vez mais complexa, se isso é possível?
Eu sempre penso: "Dê o máximo de trabalho possível ao banco de dados". Não tenho certeza sobre este!
get_posts()
, entãoget_post_meta()
para cada um deles? @MannyFleurmond, é difícil encontrar informações difíceis sobre o cache interno do WP, mas o AFAIK armazenaria em cache as informações por solicitação. A chamada para o servidor para coletar esses dados é uma chamada AJAX, e acho que nada mais estará pegando coisas antes dela.Respostas:
As meta-informações de postagem são armazenadas em cache automaticamente na memória para um padrão
WP_Query
(e a consulta principal), a menos que você diga especificamente para não fazer isso usando oupdate_post_meta_cache
parâmetroPortanto, você não deve escrever suas próprias consultas para isso.
Como o meta caching funciona para consultas normais:
Se o
update_post_meta_cache
parâmetro paraWP_Query
não estiver definido como false, depois que as postagens forem recuperadas do banco de dados, aupdate_post_caches()
função será chamada, que por sua vez chamaupdate_postmeta_cache()
.A
update_postmeta_cache()
função é um invólucroupdate_meta_cache()
e essencialmente chama um simplesSELECT
com todos os IDs das postagens recuperadas. Isso fará com que ele obtenha todos os postmeta, para todas as postagens na consulta, e salve esses dados no cache do objeto (usandowp_cache_add()
).Quando você faz algo parecido
get_post_custom()
, ele verifica primeiro o cache do objeto. Portanto, não é necessário fazer consultas adicionais para obter a meta da postagem neste momento. Se você recebeu a postagem em umWP_Query
, a meta já está na memória e a obtém diretamente a partir daí.As vantagens aqui são muitas vezes maiores do que fazer uma consulta complexa, mas a maior vantagem vem do uso do cache de objetos. Se você usar uma solução de cache de memória persistente como XCache ou memcached ou APC ou algo assim, e tiver um plug-in que possa vincular seu cache de objetos a ele (W3 Total Cache, por exemplo), todo o cache de objetos será armazenado na memória rápida já. Nesse caso, há zero de consultas necessárias para recuperar seus dados; já está na memória. O cache de objetos persistentes é impressionante em muitos aspectos.
Em outras palavras, sua consulta provavelmente carrega e carrega mais lentamente do que usar uma consulta adequada e uma solução simples de memória persistente. Use o normal
WP_Query
. Poupe algum esforço.Adicional:
update_meta_cache()
é inteligente, BTW. Ele não recuperará as meta informações para postagens que já tenham suas meta informações em cache. Não obtém a mesma meta duas vezes, basicamente. Super eficiente.Adicional adicional: "Dê o máximo de trabalho possível ao banco de dados." ... Não, esta é a web. Regras diferentes se aplicam. Em geral, você sempre deseja dar o mínimo de trabalho possível ao banco de dados, se for possível. Os bancos de dados são lentos ou mal configurados (se você não o configurou especificamente, pode apostar que isso é verdade). Muitas vezes, eles são compartilhados entre muitos sites e sobrecarregados até certo ponto. Normalmente você tem mais servidores web do que bancos de dados. Em geral, você deseja apenas obter os dados que deseja do banco de dados o mais rápido e simples possível e, em seguida, classificá-los usando o código do servidor da web. Como princípio geral, é claro, casos diferentes são todos diferentes.
fonte
Eu recomendaria uma consulta dinâmica. Usando seu exemplo:
fonte
Me deparei com um caso em que também quero recuperar rapidamente muitas postagens com suas meta informações associadas. Preciso recuperar postagens O (2000).
Eu tentei usando a sugestão de Otto - executando WP_Query :: query para todas as postagens e, em seguida, repetindo e executando get_post_custom para cada post. Isso levou, em média, cerca de 3 segundos para ser concluído .
Então tentei a consulta dinâmica de Ethan (embora não gostasse de pedir manualmente cada meta_key em que me interessasse). Eu ainda tinha que percorrer todas as postagens recuperadas para desserializar o meta_value. Isso levou, em média, cerca de 1,3 segundos para ser concluído .
Tentei usar a função GROUP_CONCAT e encontrei o melhor resultado. Aqui está o código:
Isso levou em média 0,7 segundos . Isso ocorre cerca de um quarto do tempo da solução get_post_custom () do WP e cerca de metade da solução de consulta dinâmica.
Talvez isso seja do interesse de alguém.
fonte
Eu me encontrei em uma situação na qual precisava executar esta tarefa para criar um documento CSV, acabei trabalhando diretamente com o mysql para fazer isso. Meu código une as tabelas de postagem e meta para recuperar as informações de preços do woocommerce, a solução postada anteriormente exigia que eu usasse aliases de tabela no sql para funcionar corretamente.
Porém, lembre-se de que o woocommerce criou mais de 300 mil linhas na minha tabela meta, por isso era muito grande e, portanto, muito lento.
fonte
SEM VERSÃO SQL:
Obtenha todas as postagens e todos os seus meta-valores (metas) sem SQL:
Digamos que você tenha uma lista de IDs de postagem armazenados como uma matriz de IDs, algo como
Agora, não é possível obter todas as postagens e todas as metas em uma consulta sem usar pelo menos um pouco de SQL; portanto, devemos fazer duas consultas (ainda apenas duas):
1. Obtenha todas as postagens (usando WP_Query )
(Não se esqueça de ligar
wp_reset_postdata();
se você estiver fazendo um "loop" depois;))2. Atualize o meta cache
Para obter os metadados, basta usar o padrão
get_post_meta()
que, como o @Otto apontou:examina primeiro o cache :)
Nota: Se você realmente não precisa de outros dados das postagens (como título, conteúdo, ...), pode fazer apenas 2. :-)
fonte
usando o formulário de solução trevor e modificando-o para trabalhar com SQL aninhado. Isso não foi testado.
fonte
Corri para o problema de vários campos meta de valor também. O problema está no próprio WordPress. Procure em wp-includes / meta.php. Procure esta linha:
O problema está na instrução CAST. Em uma consulta para valores meta, a variável $ meta_type é definida como CHAR. Não sei os detalhes de como CASTing o valor para CHAR afeta a sequência serializada, mas para corrigi-lo, você pode remover a conversão para que o SQL fique assim:
Agora, mesmo que isso funcione, você está mexendo com os internos do WordPress, para que outras coisas possam quebrar, e não é uma solução permanente, supondo que você precise atualizar o WordPress.
A maneira como eu o corrigi é copiar o SQL gerado pelo WordPress para a meta consulta que eu quero e, em seguida, escrever um pouco de PHP para adicionar instruções AND adicionais aos meta_values que estou procurando e usar $ wpdb-> get_results ($ sql ) para a saída final. Hacky, mas funciona.
fonte
get_meta_sql
filtro que segue esta linha seria, obviamente, preferível ao hackear o código principal.