Interroger tous les messages où une clé méta n'existe pas

50

J'essaie d'obtenir une requête pour récupérer tous les messages où un spécifique meta_keyn'existe pas, puis le créer.

J'ai des problèmes pour trouver ces publications, car la requête que je teste ne semble pas fonctionner.

Voici le code que j'utilise pour essayer de recevoir ces publications:

$args = array(
   'posts_per_page' => 18,
   'cat'=>1955,
   'post_status'=>'publish',
   'meta_query' => array(
                  array(
                     'key' => 'colors',
                     'compare' => 'NOT EXISTS'
                  ),
   ));      

query_posts($args);

Cela ne retourne rien s'il n'y a pas de messages avec la clé colors, mais les renvoie idsavec la clé colorschaque fois que cette clé est présente (l'inverse de ce dont j'ai besoin). J'ai essayé avec EXISTau lieu mais pas de chance.

Si quelqu'un peut me conseiller sur la manière correcte de créer une requête comme celle dont j'ai besoin, je l'apprécierai.

Merci!

JordanBel
la source
Quelle version de WordPress utilisez-vous?
s_ha_dum
Salut, désolé pour l'omission. J'utilise v3.5
JordanBel
Il semble que ce type de requête (avec le paramètre de comparaison défini sur NOT EXISTS) ait été ajouté dans la version 3.5; il devrait donc fonctionner tel quel, à ma connaissance. Il serait facile de le faire via une requête SELECT personnalisée, cependant ...
Tomas Buteler
Merci, je vais essayer d'utiliser select. Je dois apprendre avant quelles tables interroger et comment se conformer à la requête :(
JordanBel
Très étrange. Je ne peux pas repérer un problème avec ce code et vous utilisez 3.5+, c'est pourquoi j'ai demandé. Avez-vous examiné la base de données pour confirmer que vos données sont insérées comme vous le pensez?
dimanche

Réponses:

73

J'ai fait quelques tests supplémentaires avec cela, et honnêtement, je ne trouve pas de raison que cela ne fonctionne pas (à moins que le code ci-dessus ne soit qu'un extrait et que le code réel corresponde à mes exemples ci-dessous). J'ai toutefois découvert quelques éléments qui pourraient vous conduire dans la bonne direction.

1) En elle-même, cette méta-requête est l’équivalent de "colors IS NULL", c’est-à-dire qu’elle renverra les publications qui n’ont pas cette clé définie dans la table postmeta. C'est le cas montré ci-dessus, et cela aurait dû fonctionner.

'meta_query' => array(
    array(
     'key' => 'colors',
     'compare' => 'NOT EXISTS' // this should work...
    ),
)

2) Avant WordPress 3.9, établir l’index de 'relation' sur 'OU' change cette condition. Il retourne le contraire. Ne me demande pas pourquoi. Ceci est particulièrement important lorsque vous effectuez plusieurs méta-requêtes. Cela signifie qu'il n'est pas initialement possible d'effectuer une requête pour les publications pour lesquelles la clé "couleurs" est définie sur "bleu" (ou autre) ou n'est pas définie du tout. La requête ci-dessous ignorera la première condition et renverra uniquement celles qui correspondent à la deuxième condition.

'meta_query' => array(
   'relation' => 'OR',
    array(
     'key' => 'colors',
     'compare' => 'NOT EXISTS' // doesn't work
    ),
    array(
     'key' => 'colors',
     'value' => 'blue'
    )
)

3) Cependant, nous pouvons tromper WordPress en utilisant la première condition si nous définissons la "valeur". Elle n'a pas besoin d'une valeur pertinente (elle est ignorée, autant que je sache), mais elle doit être définie pour que la NOT EXISTScondition ait un effet.

'meta_query' => array(
   'relation' => 'OR',
    array(
     'key' => 'colors',
     'compare' => 'NOT EXISTS', // works!
     'value' => '' // This is ignored, but is necessary...
    ),
    array(
     'key' => 'colors',
     'value' => 'blue'
    )
)

C'était vrai jusqu'à WordPress 3.9. Si vous utilisez toujours une version plus ancienne, cette solution de contournement est viable.

Tomas Buteler
la source
Merci! Et désolé pour le retard. J'ai fini par utiliser une requête, mais je testerai votre solution dans les prochaines heures afin de pouvoir revenir en arrière et peut-être que si cela fonctionne, nous pouvons en aider d'autres. Je vous le ferai savoir dès que je pourrai vérifier. Merci encore
JordanBel
Bien écrit et confirmé que l’ajout d’une valeur vide renvoie les résultats attendus. Je dirais que c'est involontaire et qu'il vaut peut-être mieux jeter un coup d'œil à trac.wordpress.org pour voir s'il existe déjà un ticket, sinon, il est reproductible.
Taylor Dewey
Merci pour l'excellente explication et la solution pour tromper WP :) Cela a pris un peu de temps pour arriver ici - mais maintenant je veux cliquer sur le vote vers le haut pour au moins 10 fois (si seulement je pouvais;))
singe lorem
Si j'utilise compare EXISTS, la valeur n'est malheureusement pas ignorée dans les versions les plus récentes de WP (testé en 4.2.2)
Igor Jerosimić
10
Le EXISTSet NOT EXISTS"bug" qui vous demandait de spécifier une valeur a été corrigé dans WP 3.9
trex005
11

En utilisant une requête personnalisée, cela a fonctionné pour moi:

SELECT * FROM wp_posts as posts
            WHERE   posts.post_type     = 'post'
            AND NOT EXISTS (
              SELECT * FROM `wp_postmeta`
               WHERE `wp_postmeta`.`meta_key` = "your_meta_key"
                AND `wp_postmeta`.`post_id`=posts.ID
            ) 
i_a
la source