Ich habe die integrierte WP-Suche mithilfe des pre_get_posts
Filters geändert, sodass der Benutzer die Beiträge (einschließlich einer Reihe benutzerdefinierter Beitragstypen) nach verschiedenen Feldern sortieren kann.
Das Problem, das ich habe, ist, dass wenn ich WP anweise, nach einem Meta-Wert zu sortieren, alle Posts ausgeschlossen werden, für die dieser Meta-Wert nicht festgelegt ist. Dies führt dazu, dass sich die Anzahl der Ergebnisse ändert, wenn Sie die Sortierung von "Preis" auf "Datum" ändern, da für "Beiträge" nicht "Preis" festgelegt ist, sondern "Artikel".
Dies ist nicht das, was ich will, also würde ich gerne wissen, ob es eine Möglichkeit gibt, ALLE Posts einzuschließen - auch diejenigen, denen der Meta-Wert fehlt, nach dem ich sortiere - und denjenigen ohne den letzten Wert zu setzen.
Ich weiß, wie man nach mehr als einem Feld sortiert, aber das hilft nicht.
Vielen Dank
Scheint, ich bin nicht der einzige mit dieser Frage: Wie kann ich Posts mit und ohne bestimmten meta_key in args for wp_query aufnehmen? aber da gibt es keine lösung.
Aktualisieren
Ich habe die Antwort ausprobiert, bin mir aber nicht sicher, ob ich sie richtig verstanden habe:
<?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');
}
Der Meta-Wert ist eine Zahl (er wird verwendet, um einen Preis zu speichern, wie der Name vermuten lässt.)
Update 2
Ich habe die Bestellung auskommentiert und alles, was ich jetzt habe, ist Folgendes:
<?php
$qry->set('meta_query', array(array(
'key' => 'item_price',
'value' => '',
'compare' => 'NOT EXISTS'
)));
Mit diesem Code scheint die Abfrage alle Posts zurückzugeben, bei denen der item_price
Schlüssel fehlt, und keinen der Posts, bei denen er vorhanden ist. IE das Problem ist jetzt umgekehrt.
Wenn ich auch den Bestellcode hinzufüge, erhalte ich 0 Ergebnisse.
Edit: ... drei Jahre später ... : PI hatte dieses Problem erneut. Ich habe alle Antworten ausprobiert und keine funktioniert. Ich bin mir nicht sicher, warum manche Leute glauben, dass sie funktionieren, aber sie arbeiten zumindest nicht für mich.
Die Lösung, die ich gefunden habe, ist die Verwendung des save_post
Filters - stellen Sie sicher, dass alle Beiträge das benutzerdefinierte Feld haben, nach dem ich sortieren möchte. Es ist ein bisschen nervig, dass ich es tun muss, aber solange Sie es früh tun, werden Sie wahrscheinlich keine Probleme haben.
In diesem Fall habe ich einen "View Counter" für Posts erstellt und wollte, dass Benutzer in der Lage sind, die am häufigsten gelesenen Posts zu sortieren. Auch hier sind Beiträge, die noch nie gesehen wurden (ich denke, das ist ziemlich unwahrscheinlich - aber immer noch), verschwunden, wenn nach Ansichtsanzahl sortiert wurde. Ich habe diesen Code hinzugefügt, um sicherzustellen, dass alle Beiträge eine Anzahl von Ansichten haben:
add_action('save_post', function ($postId) {
add_post_meta($postId, '_sleek_view_count', 0, true);
});
quelle
meta_query
undtax_query
sind immer ein,array( array() )
da sie mehrere Arrays kombinieren. Zweitens - wie in meiner Antwort erwähnt - müssen Siemeta_value_num
für Zahlen verwenden. Es kann genauso gut erforderlich sein, um den Eintrag tatsächlich zu definierenmeta_value_num
(sieheWP_Query
-Codex-Seiteneintrag). Zuletzt macht es keinen Sinn,order
inASC
undDESC
Richtung zu gehen. Das ist doch nicht möglich. Der Raumbegrenzer funktioniert nur fürorderby
und Sie können ihm nicht sagen, dass er den erstenASC
und den zweiten sortieren sollDESC
. Dafür istposts_clauses
Filter da.meta_value_num
Eingaben reelle Zahlen sind. Zu oft gesehen, dass jemand angibt, dass es sich um eine Zahl handelt, diese aber tatsächlich als Zeichenfolge in der Datenbank speichert.ASC DESC
ist, dass es nach meinem Kenntnisstand nachmeta_value
InASC
unddate
In sortiertDESC
.Antworten:
Hierfür gibt es zwei mögliche Lösungen:
1. Alle Beiträge haben Meta
Die beste Lösung, die ich hier gefunden habe, besteht darin, den restlichen Artikeln / Produkten einen Artikelpreis von 0 zuzuweisen. Sie können dies manuell ausführen oder alle Artikel durchlaufen. Wenn der Preis leer ist, aktualisieren Sie ihn.
Um dies in Zukunft handhabbar zu machen, können Sie sich einbinden
save_post
und ihnen einen Wert zuweisen, wenn sie zum ersten Mal hinzugefügt werden (nur wenn dieser leer ist).2. Mehrere Abfragen
Sie können die erste Abfrage währenddessen ausführen und die IDs der zurückgegebenen Posts speichern. Sie können dann eine weitere Abfrage für alle Posts und das Bestelldatum ausführen, ohne die IDs, die von der ersten Abfrage zurückgegeben werden.
Sie können dann die beiden Ergebnisse separat bestellen und Sie erhalten die gewünschten Ergebnisse.
quelle
save_post
Methode verwenden (Ich habe meine Frage mit dem von mir verwendeten Code aktualisiert).Easy Peasy, gerade 2018 getestet, wird derzeit in der Produktion verwendet.
Hiermit wird nach allen Elementen mit und ohne Metaschlüssel gesucht, für die kein Wert angegeben wurde. Die Meta-Abfrage liefert zuverlässig den Schlüssel für die Bestellung. Es wurde getestet. Ich bin mir jedoch nicht sicher, wie es funktionieren wird, wenn die Meta-Abfrage mehrere Schlüssel verwendet.
Praktisches Beispiel
Dadurch werden Beiträge
custom_meta_key
standardmäßig sortiert und Beiträge ohne einen Wert für diesen Schlüssel nicht ignoriert.quelle
custom_meta_key
und Beiträge bekommen, die nicht habencustom_meta_key
. Fühlen Sie sich frei, ein aktuelles Arbeitsbeispiel in die Sortierung aufzunehmen.$query->set( 'orderby', 'meta_value title' );
(Nach Meta-Wert und dann nach Titel sortieren, wenn mehrere Beiträge den gleichen Wert für den Meta-Schlüssel haben.) Dies sollte impre_get_posts
Hook mithilfe der übergebenen$query
Variablen erfolgen. Beachten Sie, dass die Frage lautete, wie nach Meta-Wert sortiert werden soll, während Posts, die keinen Wert für diesen Meta-Schlüssel haben, nicht ignoriert werden.get_posts()
Aufruf, um Beiträge mit_featured
Meta nach oben zu schieben und danach nach Datum zu bestellen. Vielen Dank!Diese Methode gibt alle Posts zurück, einschließlich der mit und ohne den angeforderten.
meta_key
Bei der Bestellung werden jedoch merkwürdige Dinge ausgeführt.Ich fand dies, indem ich mit all den verschiedenen Antworten auf diese Frage herumspielte und das generierte SQL durch Ausprobieren analysierte . Es scheint, dass das Festlegen von
array('meta_query' => array('relation' => 'OR'))
Ausgaben eine angemesseneLEFT JOIN
OptionINNER JOIN
ist, um Posts einzuschließen, bei denen die Metadaten fehlen. Das Festlegen vonNOT EXISTS
verhindert, dass dieWHERE
Klausel Beiträge herausfiltert, denen das Metafeld fehlt. Für dieses spezielleWP_Query
ist das generierte SQL (Einrückung / Zeilenumbruch hinzugefügt):Das Ergebnis ist eine Liste aller Beiträge mit meta_value von
item_price
und Vermisstenitem_price
. Alle der Pfosten mititem_price
korrekt relativ zueinander bestellt werden, aber Beiträge fehlenitem_price
werden einige zufällige verwenden andere Meta - Wert (sagen wir,_edit_last
was zu sein scheint1
für seine in der Datenbank oder eine andere interne Wordpress - Metadaten , die völlig willkürlich ist ziemlich oft)wp_postmeta.meta_value
in dieORDER BY
Klausel. Während diese Methode nahe beieinander liegt und für bestimmte Daten zu funktionieren scheint, ist sie fehlerhaft. Alles, was ich sagen kann, ist, wenn Ihreitem_price
Werte nicht mit den zufälligen Metafeldern in Konflikt stehen, die MySQL für die fehlenden Posts auswähltitem_price
, könnte dies für Sie in Ordnung sein. Wenn alles, was Sie brauchen, ist eine Garantie, dass Ihre Beiträge mititem_price
korrekt in Bezug zueinander angeordnet sind, ohne Rücksicht auf die Anordnung anderer Beiträge, kann es in Ordnung sein. Aber ich denke, das ist nur ein Mangel in WordPress. Bitte korrigieren Sie mich, ich hoffe, ich liege falsch und es gibt einen Weg, dies zu beheben ;-).Es scheint, dass
INNER JOIN wp_postmeta
MySQL für die eine zufällige Zeile aus mehrerenpostmeta
Zeilen auswählt, die dem Beitrag zugeordnet sind, wenn diemeta_key
in dem angegebenen Beitrag fehlt. Aus SQL-Sicht müssen wir herausfinden, wie WordPress zur Ausgabe angewiesen wirdORDER BY mt1.meta_value
. Diese Spalte ist im Gegensatz zu richtig,NULL
wenn unsere angefordertemeta_key
fehltwp_postmeta.meta_value
. Wenn wir das tun könnten, würde SQL dieseNULL
(fehlenden Einträge) vor jedem anderen Wert sortieren und uns eine klar definierte Reihenfolge geben: Zuerst kommen alle Beiträge, denen das jeweilige Postmetafeld fehlt, und dann die Beiträge mit dem Feld. Aber das ist das ganze Problem:'orderby' => 'meta_value'
Kann sich nur beziehen'meta_key' => 'item_price'
und das Unausgeglichenewp_postmeta
ist immer einINNER JOIN
statt immer einLEFT JOIN
, Sinnwp_postmeta.meta_value
undwp_postmeta.meta_key
kannniemals seinNULL
.Ich muss also sagen, dass dies mit WordPress nicht möglich ist,
WP_Query
da es jetzt dokumentiert ist (in WordPress-3.9.1). Mühe. Wenn Sie dies also wirklich benötigen, um richtig zu funktionieren, müssen Sie sich wahrscheinlich an einer anderen Stelle in WordPress einbinden und die generierte SQL direkt ändern .quelle
Ich denke ich habe eine Lösung.
Sie können zwei
meta_key
s verwenden, eine, die alle Beiträge haben(like "_thumbnail_id")
, und die, diemeta_key
Sie als Filter verwenden möchten.Also deine Argumente:
quelle
'value' => '',
auch der zweite Vergleich sollte seinNOT EXISTS
und die letzte gesetzte Anweisung ist nicht erforderlichDas Problem, das jeder hier hat, hat mit der Reihenfolge der Meta-Abfragen zu tun. Um richtig zu sortieren, müssen Sie die Abfrage "NOT EXISTS" vor die Abfrage "EXISTS" setzen.
Der Grund dafür ist, dass WordPress den meta_value der letzten "LEFT JOIN" -Anweisung in der "ORDER BY" -Klausel verwendet.
Beispielsweise:
quelle
Bei Bedarf können Sie jedes Mal, wenn ein Beitrag gespeichert oder aktualisiert wird, einen Standard-Metawert hinzufügen, wenn der Metawert nicht vorhanden ist.
Wenn Sie einen benutzerdefinierten Beitragstyp verwenden, ersetzen Sie den
add_action('save_post', 'addDefaultMetaValue');
durchadd_action('save_post_{post_type}', 'addDefaultMetaValue');
zadd_action('save_post_product', 'addDefaultMetaValue');
quelle
Ich hatte das Problem alleine für numerische Metawerte und wies darauf hin, dass es auch auf die Reihenfolge der Abfrage ankommt. Für mich muss die
NOT EXISTS
Abfrage die erste sein.Beispiel:
Ebenfalls wichtig, um die richtige Richtung für numerische Werte zu erhalten, ist die allgemeine
’orderby’
Einstellung’meta_value_num’
. Ansonsten haben Sie seltsame Ergebnisse für numerische Werte, zB:1, 2, 20, 21, 3, 4, 5…
Anstatt:
1, 2, 3, 4, 5… 20, 21
quelle
Ich bin auch auf ein ähnliches Problem gestoßen und die folgende Lösung hat mir geholfen:
Ich habe auf WordPress Codex eine Beschreibung mit dem Titel " 'orderby' mit mehreren 'meta_key's " gefunden: https://codex.wordpress.org/Class_Reference/WP_Query#Order_.26_Orderby_Parameters
quelle
Dafür gibt es einen möglichen
orderby
Wertmeta_value
.Wenn Sie numerische Werte haben, verwenden Sie
meta_value_num
stattdessen einfach .Haftungsausschluss: Dies ist nicht getestet, aber es sollte funktionieren. Punkt ist, dass Sie Ihre
meta_key
undkey
Werte angeben müssen . Ansonsten können Sie nicht mit nicht vorhandenen Werten vergleichen, wodurch es möglich sein sollte, beide Arten von Posts abzufragen. Es ist eine Art Hack-ish, aber solange es funktioniert ...quelle
'your_keys_name'
und'your_meta_key'
sollten beide die gleiche Zeichenfolge sein, anstatt sich zu unterscheiden, sonst sieht es so aus, als hätten Sie die Frage falsch verstanden. Zweitens habe ich dies auf meinem lokalen Setup getestet und es werden alle Posts ausgeschlossen, bei denen der Schlüssel vorhanden ist (durchmeta_query
), und alle Posts, bei denen der Schlüssel fehlt (durchmeta_key
), was dazu führt, dass keine Posts angezeigt werden. Diese Antwort ist jedoch ein Schritt in Richtung etwas, das zumindest Worte ;-).'relation' => 'OR'
zumeta_query
. Verrücktes Zeug o_o.Ich denke , was @kaiser versuchte , war zu tun , um die Abfrage zu sagen , alle Beiträge zurückzugeben, dass Meta - Schlüssel durch eine Art Dummy - Anwendung , wo Zustand zu nicht einem dieser Beiträge zu filtern. Wenn Sie also wissen, dass alle Werte, die Ihre benutzerdefinierten Felder annehmen können, x, y, z sind, können Sie sagen: "WHERE meta_key IN (x, y, z) ". Sie können dieses Problem jedoch vermeiden, indem Sie sagen:! = (' ') :
Auch nicht getestet, aber es scheint einen Versuch wert zu sein :-).
quelle
Ich habe das mit ein bisschen Hack (IMHO) umgangen, aber es hat in meinem Fall die Arbeit für mich erledigt.
Sie können die Filter posts_join_paged und posts_orderby verwenden , um die Verknüpfungs- und Ordnungszeichenfolgen zu aktualisieren. Auf diese Weise können Sie nach Belieben bestellen, solange Sie sich zuerst anmelden und nicht nach WP_Query, vorausgesetzt, das Feld muss für diesen bestimmten Beitrag vorhanden sein. Sie können dann entfernen Sie das
meta_key
,orderby
und `Bestellung von Ihrem WP_Query args.Unten ist ein Beispiel. Am Anfang jeder Funktion musste ich für bestimmte Fälle aussteigen, da dies zu allem hinzugefügt wird, was WP_Query verwendet. Möglicherweise müssen Sie dies ändern, um es an Ihre speziellen Bedürfnisse anzupassen.
Die Dokumentation zu diesen beiden Filtern fehlt leider so ... viel Glück! :)
quelle
cast(my_custom_meta_key.meta_value as unsigned) DESC
sollte den Trick tun ...$orderby_statement = "cast(my_custom_meta_key.meta_value as unsigned) DESC";
funktioniert super.Diese Lösung hat bei mir funktioniert:
Diese Lösung zeigt jedoch zuerst die Datensätze mit null meta_value an. Diese andere Lösung zeigt ASC-Reihenfolge und Nullen am Ende:
quelle