Ich brauche eine Reihe von Posts mit ihren Metadaten. Natürlich können Sie mit einer Standardpost-Abfrage keine Metadaten abrufen, daher müssen Sie in der Regel eine get_post_custom()
für jeden Post durchführen.
Ich versuche es mit einer benutzerdefinierten Abfrage, wie folgt:
$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'
");
Scheint zu funktionieren. Es wird ausgelöst, wenn Sie eines dieser Metafelder so verwenden, dass mehrere Metawerte für denselben Beitrag zulässig sind. Ich kann mir keine Verbindung vorstellen, um das zu tun.
Frage 1: Gibt es eine Verknüpfung, Unterabfrage oder was auch immer, um Metafelder mit mehreren Werten einzufügen?
Aber Frage 2: Lohnt es sich? Wie viele postmeta
Tabellenverknüpfungen füge ich hinzu, bevor ein Ansatz mit zwei Abfragen bevorzugt wird? Ich könnte alle Post-Daten in einer Abfrage erfassen, dann alle relevanten Post-Metas in einer anderen und das Meta mit den Post-Daten in einer Ergebnismenge in PHP kombinieren. Wäre das schneller als eine einzelne, immer komplexer werdende SQL-Abfrage, wenn das überhaupt möglich wäre?
Ich denke immer: "Gib der Datenbank so viel Arbeit wie möglich." Ich bin mir nicht sicher!
get_posts()
dannget_post_meta()
für jeden dieser Posts ? @MannyFleurmond, es ist schwer, genaue Informationen über das in WP integrierte Caching zu finden, aber AFAIK würde es Sachen pro Anfrage zwischenspeichern. Der Aufruf an den Server, um diese Daten abzurufen, ist ein AJAX-Aufruf, und ich glaube nicht, dass irgendetwas anderes zuvor Dinge abrufen wird.Antworten:
Post-Meta-Informationen werden für einen Standard
WP_Query
(und die Hauptabfrage) automatisch im Arbeitsspeicher zwischengespeichert , es sei denn, Sie weisen ihn ausdrücklich an, dies nicht mithilfe desupdate_post_meta_cache
Parameters zu tun .Daher sollten Sie hierfür keine eigenen Abfragen schreiben.
So funktioniert das Meta-Caching bei normalen Abfragen:
Wenn der
update_post_meta_cache
Parameter für denWP_Query
nicht auf false gesetzt ist, wird nach dem Abrufen der Beiträge aus dem DB dieupdate_post_caches()
Funktion aufgerufen, die wiederum aufruftupdate_postmeta_cache()
.Die
update_postmeta_cache()
Funktion ist ein Wrapper fürupdate_meta_cache()
und ruft im Wesentlichen eine einfacheSELECT
ID mit allen IDs der abgerufenen Posts auf. Dadurch erhält es das gesamte Postmetall für alle Posts in der Abfrage und speichert diese Daten im Objektcache (mithilfe vonwp_cache_add()
).Wenn Sie so etwas tun
get_post_custom()
, wird zuerst der Objektcache überprüft. Daher sind an dieser Stelle keine zusätzlichen Abfragen erforderlich, um das Post-Meta abzurufen. Wenn Sie den Beitrag in a erhalten habenWP_Query
, befindet sich das Meta bereits im Speicher und wird direkt von dort abgerufen.Die Vorteile sind hier um ein Vielfaches größer als bei einer komplexen Abfrage. Der größte Vorteil ergibt sich jedoch aus der Verwendung des Objektcaches. Wenn Sie eine permanente Speicher-Caching-Lösung wie XCache oder memcached oder APC oder ähnliches verwenden und ein Plugin haben, das Ihren Objekt-Cache daran binden kann (z. B. W3 Total Cache), wird Ihr gesamter Objekt-Cache im schnellen Speicher gespeichert bereits. In diesem Fall sind keine Abfragen erforderlich, um Ihre Daten abzurufen. es ist schon in Erinnerung. Das dauerhafte Zwischenspeichern von Objekten ist in vielerlei Hinsicht fantastisch.
Mit anderen Worten, Ihre Abfrage wird wahrscheinlich immer langsamer geladen als eine ordnungsgemäße Abfrage und eine einfache persistente Speicherlösung. Verwenden Sie die normale
WP_Query
. Sparen Sie sich etwas Mühe.Zusätzlich:
update_meta_cache()
ist schlau, Übrigens. Es werden keine Metainformationen für Posts abgerufen, deren Metainformationen bereits zwischengespeichert sind. Im Grunde genommen bekommt es nicht zweimal das gleiche Meta. Super effizient.Zusätzlicher Zusatz: "Geben Sie der Datenbank so viel Arbeit wie möglich." ... Nein, das ist das Web. Es gelten andere Regeln. Im Allgemeinen möchten Sie der Datenbank immer so wenig Arbeit wie möglich widmen, wenn dies machbar ist. Datenbanken sind langsam oder schlecht konfiguriert (wenn Sie sie nicht speziell konfiguriert haben, können Sie mit gutem Geld darauf wetten, dass dies wahr ist). Oft werden sie von vielen Websites gemeinsam genutzt und sind bis zu einem gewissen Grad überlastet. Normalerweise haben Sie mehr Webserver als Datenbanken. Im Allgemeinen möchten Sie die gewünschten Daten so schnell und einfach wie möglich aus der Datenbank holen und sie dann mit dem Code auf der Seite des Webservers aussortieren. Grundsätzlich sind natürlich alle Fälle unterschiedlich.
quelle
Ich würde eine Pivot-Abfrage empfehlen. Verwenden Sie Ihr Beispiel:
quelle
Ich bin auf einen Fall gestoßen, in dem ich auch schnell viele Beiträge mit den dazugehörigen Metainformationen abrufen möchte. Ich muss O (2000) Posts abrufen.
Ich habe es mit Ottos Vorschlag versucht - WP_Query :: query für alle Posts ausführen und dann get_post_custom für jeden Post durchlaufen und ausführen. Dies dauerte durchschnittlich etwa 3 Sekunden .
Ich habe dann Ethans Pivot-Abfrage ausprobiert (obwohl ich nicht gerne manuell nach jedem meta_key fragen musste, der mich interessiert hat). Ich musste immer noch alle abgerufenen Beiträge durchlaufen, um den meta_value zu unserialisieren. Dies dauerte durchschnittlich etwa 1,3 Sekunden .
Ich habe dann versucht, die GROUP_CONCAT-Funktion zu verwenden, und das beste Ergebnis gefunden. Hier ist der Code:
Dies dauerte durchschnittlich 0,7 Sekunden . Das ist ungefähr ein Viertel der Zeit der WP-Lösung get_post_custom () und ungefähr die Hälfte der Pivot-Abfragelösung.
Vielleicht ist das für jemanden von Interesse.
quelle
Ich befand mich in einer Situation, in der ich diese Aufgabe erledigen musste, um letztendlich ein CSV-Dokument zu erstellen. Am Ende arbeitete ich direkt mit mysql zusammen, um dies zu tun. Mein Code verknüpft die Post- und Metatabellen, um Woocommerce-Preisinformationen abzurufen. Die zuvor veröffentlichte Lösung erforderte, dass ich Tabellenaliase in der SQL verwende, um ordnungsgemäß zu funktionieren.
Seien Sie jedoch gewarnt, woocommerce hat über 300.000 Zeilen in meiner Metatabelle erstellt, daher war diese sehr groß und daher sehr langsam.
quelle
KEINE SQL VERSION:
Holen Sie sich alle Beiträge und alle ihre Meta-Werte (Metas) ohne SQL:
Angenommen, Sie haben eine Liste von Beitrags-IDs, die in Form eines Arrays von IDs gespeichert sind
Jetzt ist es nicht möglich, alle Posts und Metas in einer Abfrage zu erhalten, ohne mindestens ein bisschen SQL zu verwenden. Wir müssen also zwei Abfragen durchführen (immer noch nur zwei):
1. Holen Sie sich alle Beiträge (mit WP_Query )
(Vergiss nicht anzurufen,
wp_reset_postdata();
wenn du danach eine "Schleife" machst ;))2. Aktualisieren Sie den Meta-Cache
Um die Metadaten zu erhalten, verwenden Sie einfach den Standard,
get_post_meta()
der, wie @Otto betonte: zuerstin den Cache schaut :)
Hinweis: Wenn Sie keine weiteren Daten aus den Posts benötigen (wie Titel, Inhalt, ...) , können Sie nur 2 machen. :-)
quelle
Verwenden Sie das Lösungsformular trevor und ändern Sie es, um mit verschachteltem SQL zu arbeiten. Dies wird nicht getestet.
quelle
Ich bin auch auf das Problem der Metafelder mit mehreren Werten gestoßen. Das Problem ist mit WordPress selbst. Schau in wp-includes / meta.php. Suchen Sie nach dieser Zeile:
Das Problem ist mit der CAST-Anweisung. In einer Abfrage nach Metawerten wird die Variable $ meta_type auf CHAR gesetzt. Ich weiß nicht genau, wie sich das Casting des Werts auf CHAR auf die serialisierte Zeichenfolge auswirkt. Um dies zu beheben, können Sie die Umwandlung entfernen, sodass die SQL wie folgt aussieht:
Jetzt, obwohl das funktioniert, sind Sie mit den WordPress-Interna fertig, so dass andere Dinge möglicherweise kaputt gehen und es ist keine dauerhafte Lösung, vorausgesetzt, Sie müssen WordPress aktualisieren.
Ich habe das Problem behoben, indem ich das von WordPress generierte SQL für die gewünschte Meta-Abfrage kopiere und dann PHP schreibe, um zusätzliche AND-Anweisungen für die gesuchten Meta-Werte zu verwenden und $ wpdb-> get_results ($ sql ) für die endgültige Ausgabe. Hacky, aber es funktioniert.
quelle
get_meta_sql
wäre natürlich besser, den Filter, der auf diese Zeile folgt , zu nutzen, als Kerncode zu hacken.