Estive modificando a pesquisa WP incorporada usando o pre_get_posts
filtro, permitindo que o usuário classifique as postagens (incluindo vários tipos personalizados de postagens) por campos diferentes.
O problema que estou tendo é que, quando digo ao WP para classificar por um meta-valor, ele exclui todas as postagens que não têm esse meta-valor definido. Isso faz com que o número de resultados mude se você alterar a classificação de dizer "Preço" para "Data" porque "Postagens" não têm "Preço" definido, mas "Itens" sim.
Não é isso que eu quero, então eu gostaria de saber se há uma maneira de incluir TODAS as postagens - mesmo aquelas que não possuem o valor meta que eu estou classificando - e colocar a que está sem o valor por último.
Eu sei como classificar em mais de um campo, mas isso não ajuda.
obrigado
Parece que eu não sou o único com esta pergunta: Maneira de incluir posts com e sem determinada meta_key em args para wp_query? mas não há solução lá.
Atualizar
Eu tentei a resposta, mas não tenho certeza se entendi corretamente, eis o que tenho agora:
<?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');
}
O meta-valor é um número (é usado para armazenar um preço como o nome sugere)
Atualização 2
Eu comentei as coisas do pedido e tudo o que tenho agora é o seguinte:
<?php
$qry->set('meta_query', array(array(
'key' => 'item_price',
'value' => '',
'compare' => 'NOT EXISTS'
)));
Com esse código, a consulta parece retornar todas as postagens que não possuem a item_price
chave e nenhuma das postagens que a possuem. Ou seja, o problema agora está invertido.
Se eu adicionar o código do pedido, também recebo 0 resultados.
Edit: ... três anos depois ... : PI teve esse problema novamente. Eu tentei todas as respostas dadas e nenhuma funcionou. Não sei por que algumas pessoas parecem pensar que funcionam, mas pelo menos não funcionam para mim.
A solução que eu acabei usando é usar o save_post
filtro - certificando-se de que todas as postagens tenham o campo personalizado que eu gostaria de classificar. É um pouco chato eu ter que fazer isso, mas contanto que você faça isso desde o início, provavelmente não terá problemas.
Nesse caso, eu estava criando um "contador de visualizações" nas postagens e queria que os usuários pudessem classificar as postagens mais lidas. Novamente, as postagens que nunca foram visualizadas (acho que é bastante improvável - mas ainda assim) desapareceram ao classificar a contagem de visualizações. Adicionei este código para garantir que todas as postagens tenham uma contagem de visualizações:
add_action('save_post', function ($postId) {
add_post_meta($postId, '_sleek_view_count', 0, true);
});
fonte
meta_query
etax_query
são sempre umarray( array() )
, pois combinam várias matrizes. Segundo - como mencionado na minha resposta - você precisa usarmeta_value_num
para números. Também pode ser necessário definir realmentemeta_value_num
(consulte aWP_Query
entrada de página -Codex). Última, não faz sentidoorder
emASC
eDESC
direção. Isso não é possível. O delimitador de espaço funciona apenas paraorderby
e você não pode ordená-lo para classificar o primeiroASC
e o segundoDESC
. É para isso queposts_clauses
serve o filtro.meta_value_num
entradas são números reais . Viu com muita frequência que alguém afirma que é um número, mas na verdade salvou-o como uma sequência no banco de dados.ASC DESC
isso é que ele classifica ometa_value
inASC
e odate
inDESC
, até onde eu sei que funciona.Respostas:
Existem duas soluções possíveis para isso:
1. Todas as postagens têm meta
A melhor solução que encontrei aqui é fornecer ao restante das postagens / produtos um preço de item igual a 0. Você pode fazer isso manualmente ou percorrer todas as postagens e, se o preço estiver vazio, atualize-o.
Para tornar isso gerenciável no futuro, você pode se conectar
save_post
e dar um valor a eles quando forem adicionados pela primeira vez (somente se estiver em branco).2. Várias consultas
Você pode executar a primeira consulta enquanto faz e armazenar os IDs das postagens retornadas. Em seguida, você pode executar outra consulta para todas as postagens e a data do pedido, excluindo os IDs retornados da primeira consulta.
Em seguida, você pode imprimir os dois resultados separadamente e obter os resultados desejados.
fonte
save_post
método (atualizei minha pergunta com o código que usei).Easy Peasy, testado em 2018, atualmente em uso.
Isso verifica todos os itens com e sem a meta-chave, sem nenhum valor especificado. a meta consulta fornece a chave do pedido com confiabilidade. Foi testado. Não tenho certeza, no entanto, de como isso funcionará quando a consulta meta usar várias chaves.
Exemplo prático
Isso ordenará as postagens por
custom_meta_key
padrão e não ignorará as postagens sem um valor para essa chave.fonte
custom_meta_key
e as postagens que não têmcustom_meta_key
. Sinta-se à vontade para incluir um exemplo de trabalho real na classificação.$query->set( 'orderby', 'meta_value title' );
(Ordene por meta-valor e depois por título quando várias postagens tiverem o mesmo valor para a meta-chave). Isso deve ser feito nopre_get_posts
gancho, usando a$query
variável passada em . Lembre-se de que a pergunta feita foi como ordenar por meta-valor, sem ignorar as postagens que não possuem um valor para essa meta-chave.get_posts()
chamada personalizada para empurrar postagens com_featured
meta para o topo e depois ordená-las por data. Obrigado!Esse método retornará todas as postagens, incluindo aquelas com e sem a solicitação
meta_key
, mas fará coisas estranhas ao fazer o pedido.Eu descobri isso brincando com todas as respostas diferentes para essa pergunta e analisando o SQL gerado por tentativa e erro. Parece que a configuração
array('meta_query' => array('relation' => 'OR'))
gera um resultado apropriado, emLEFT JOIN
vez doINNER JOIN
necessário, para incluir postagens ausentes dos metadados. A especificação deNOT EXISTS
impede que aWHERE
cláusula filtre as postagens sem o campo meta. Para issoWP_Query
, o SQL gerado é (recuo / novas linhas adicionadas):O resultado é uma lista de todas as postagens com meta_value de
item_price
e as que estão faltandoitem_price
. Todos os posts comitem_price
serão ordenados corretamente em relação ao outro, mas as mensagens faltandoitem_price
usará alguns aleatória outro valor meta (digamos,_edit_last
o que parece ser1
, muitas vezes no meu banco de dados ou algum outro metadados wordpress interna que é completamente arbitrária) para a suawp_postmeta.meta_value
em aORDER BY
cláusula. Portanto, embora esse método esteja próximo e possa parecer funcionar para determinados dados, ele está quebrado. Então, tudo o que posso dizer é que, se seusitem_price
valores não conflitarem com os meta campos aleatórios que o MySQL escolher para as postagens ausentesitem_price
, isso poderá funcionar bem para você. Se tudo o que você precisa é garantir que suas postagens comitem_price
são ordenados corretamente em relação um ao outro, sem levar em consideração o pedido de outras postagens, pode estar OK. Mas acho que isso é apenas uma falha no wordpress. Por favor, corrija-me, espero estar errado e há uma maneira de resolver isso ;-).Parece que, para o
INNER JOIN wp_postmeta
MySQL, está escolhendo uma linha aleatória dentre váriaspostmeta
linhas associadas à postagem quando estameta_key
está ausente na postagem especificada. Do ponto de vista do SQL, precisamos descobrir como informar o wordpress à saídaORDER BY mt1.meta_value
. Esta coluna está corretamenteNULL
quando o nosso pedidometa_key
está ausente, ao contráriowp_postmeta.meta_value
. Se pudéssemos fazer isso, o SQL classificaria essasNULL
(entradas ausentes) antes de qualquer outro valor, dando-nos uma ordem bem definida: primeiro vêm todas as postagens que faltam no campo postmeta específico, depois as postagens que possuem o campo. Mas esse é todo o problema:'orderby' => 'meta_value'
só podemos nos referir'meta_key' => 'item_price'
e o sem paralisiawp_postmeta
é sempre um, emINNER JOIN
vez de sempre umLEFT JOIN
, significadowp_postmeta.meta_value
ewp_postmeta.meta_key
podenunca sejaNULL
.Então eu acho que tenho que dizer que isso não é possível com o wordpress embutido,
WP_Query
como agora está documentado (no wordpress-3.9.1). Incomodar. Portanto, se você realmente precisar que isso funcione corretamente, provavelmente precisará conectar-se ao wordpress em outro lugar e modificar diretamente o SQL gerado .fonte
Eu acho que tenho uma solução.
Você pode usar dois
meta_key
s, um que todas as postagens têm(like "_thumbnail_id")
e o quemeta_key
você deseja usar como filtro.Então seus argumentos:
fonte
'value' => '',
também segundo comparar deve serNOT EXISTS
ea instrução último conjunto não é necessáriaO problema que todos aqui estão enfrentando tem a ver com a ordem das meta-consultas. Para classificar corretamente, você precisará colocar a consulta "NOT EXISTS" antes da consulta "EXISTS".
A razão para isso é porque o WordPress usa o meta_value da última instrução "LEFT JOIN" na cláusula "ORDER BY".
Por exemplo:
fonte
Se adequado, você pode adicionar um meta-valor padrão sempre que uma postagem for salva ou atualizada, se o meta-valor não existir.
Se você estiver usando um tipo de pós personalizado, substitua o
add_action('save_post', 'addDefaultMetaValue');
poradd_action('save_post_{post_type}', 'addDefaultMetaValue');
exemplo,add_action('save_post_product', 'addDefaultMetaValue');
fonte
Eu tive o problema sozinho de meta-valores numéricos e apontei que a ordem da consulta também é importante. Para mim o
NOT EXISTS
consulta deve ser a primeira.Exemplo:
Também importante para obter a direção correta para valores numéricos é o
’orderby’
a ser definido’meta_value_num’
. Caso contrário, você terá resultados estranhos para valores numéricos, por exemplo:1, 2, 20, 21, 3, 4, 5…
Ao invés de:
1, 2, 3, 4, 5 ... 20, 21
fonte
Eu também encontrei um problema semelhante e a seguinte solução me ajudou:
Encontrei uma descrição no WordPress Codex com o título " 'orderby' com vários 'meta_key's ": https://codex.wordpress.org/Class_Reference/WP_Query#Order_.26_Orderby_Parameters
fonte
Existe um
orderby
valor possívelmeta_value
para isso.Se você obteve valores numéricos, basta usar
meta_value_num
.Isenção de responsabilidade: Isso não foi testado, mas deve funcionar. Ponto é que você precisa especificar seus
meta_key
ekey
valores. Caso contrário, você não poderá comparar com valores inexistentes, o que tornará possível consultar os dois tipos de postagens. É algum tipo de hack-ish, mas desde que funcione ...fonte
'your_keys_name'
e'your_meta_key'
ambos devem ter a mesma string em vez de distintos, caso contrário, parece que você entendeu mal a pergunta. Em segundo lugar, testei isso na minha configuração local e exclui todas as postagens em que a chave existe (por meio demeta_query
) e exclui as postagens em que a chave está ausente (pormeta_key
) resultando em nenhuma exibição. No entanto, esta resposta é um passo em direção a algo que exprima pelo menos ;-).'relation' => 'OR'
ameta_query
. Coisas malucas o_o.Eu acho que o que o @kaiser estava tentando fazer era dizer à consulta para retornar todas as postagens que possuem essa meta-chave, aplicando uma espécie de dummy where condition para não filtrar nenhuma dessas postagens. Portanto, se você conhece todos os valores que seus campos personalizados podem assumir são x, y, z, você pode dizer "WHERE meta_key IN (x, y, z) ", mas a idéia é que você pode evitar esse problema todos juntos dizendo ! = (' ') :
Também não testado, mas parece que vale a pena tentar :-).
fonte
Acabei contornando isso com um pouco de hack (IMHO), mas ele fez o trabalho para mim no meu caso.
Você pode conectar-se aos filtros posts_join_paged e posts_orderby para atualizar as cadeias de junção e ordem. Isso permitirá que você faça o pedido do jeito que quiser, desde que você o junte primeiro, em vez de WP_Query, supondo que o campo precise existir para essa postagem específica. Você pode remover o
meta_key
,orderby
e `fim de seus argumentos WP_Query.Abaixo está um exemplo. No topo de cada função, eu tive que escapar para determinados casos, pois isso adicionaria isso a tudo que usa o WP_Query. Pode ser necessário modificá-lo para atender às suas necessidades específicas.
Infelizmente, a documentação desses dois filtros está faltando, então ... boa sorte! :)
fonte
cast(my_custom_meta_key.meta_value as unsigned) DESC
deve fazer o truque ...$orderby_statement = "cast(my_custom_meta_key.meta_value as unsigned) DESC";
funciona bem.Esta solução funcionou para mim:
No entanto, esta solução mostra primeiro os registros com meta_value nulo. Esta outra solução mostra a ordem ASC e os valores nulos no final:
fonte