Saya perlu mendapatkan banyak posting dengan metadata mereka. Tentu saja Anda tidak bisa mendapatkan metadata dengan kueri posting standar, jadi Anda umumnya harus melakukan a get_post_custom()
untuk setiap posting.
Saya mencoba dengan satu permintaan khusus, seperti ini:
$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'
");
Tampaknya bekerja. Itu naik jika Anda menggunakan salah satu bidang meta dengan cara yang memungkinkan beberapa nilai meta untuk itu pada posting yang sama. Saya tidak bisa memikirkan bergabung untuk melakukan itu.
Jadi, pertanyaan 1: Apakah ada gabungan, sub-kueri, atau apa pun, untuk memasukkan bidang meta bernilai ganda?
Tetapi pertanyaan 2: Apakah itu sepadan? Berapa banyak postmeta
gabungan tabel yang saya tambahkan sebelum pendekatan 2-kueri lebih disukai? Saya bisa mengambil semua data pos dalam satu kueri, lalu mengambil semua postmeta yang relevan di yang lain, dan menggabungkan meta dengan data posting dalam satu resultset di PHP. Apakah itu akhirnya menjadi lebih cepat daripada satu query SQL yang semakin kompleks, jika itu mungkin?
Saya selalu berpikir, "Berikan sebanyak mungkin pekerjaan ke basis data." Tidak yakin dengan yang ini!
get_posts()
, laluget_post_meta()
untuk setiap orang? @ MannyFleurmond, sulit untuk menemukan info sulit tentang caching bawaan WP, tetapi AFAIK akan menyimpan hal-hal cache per permintaan. Panggilan ke server untuk mengambil data ini adalah panggilan AJAX, dan saya tidak berpikir hal lain akan mengambil hal-hal sebelumnya.Jawaban:
Informasi pos meta secara otomatis di-cache dalam memori untuk standar
WP_Query
(dan permintaan utama), kecuali Anda secara khusus mengatakannya untuk tidak melakukannya dengan menggunakanupdate_post_meta_cache
parameter.Karena itu, Anda tidak boleh menulis pertanyaan Anda sendiri untuk ini.
Cara kerja cache meta untuk kueri normal:
Jika
update_post_meta_cache
parameter keWP_Query
tidak disetel ke false, maka setelah posting diambil dari DB, makaupdate_post_caches()
fungsi akan dipanggil, yang pada gilirannya panggilanupdate_postmeta_cache()
.The
update_postmeta_cache()
fungsi pembungkus untukupdate_meta_cache()
, dan itu pada dasarnya panggilan sederhanaSELECT
dengan semua ID dari tulisan diambil. Ini akan membuatnya mendapatkan semua postmeta, untuk semua posting di kueri, dan menyimpan data itu dalam cache objek (menggunakanwp_cache_add()
).Ketika Anda melakukan sesuatu seperti
get_post_custom()
, itu memeriksa objek cache terlebih dahulu. Jadi itu tidak membuat pertanyaan tambahan untuk mendapatkan meta pos pada saat ini. Jika Anda mendapatkan pos di aWP_Query
, maka meta sudah ada dalam memori dan langsung mendapatkannya dari sana.Keuntungan di sini berkali-kali lebih besar daripada membuat kueri yang kompleks, tetapi keuntungan terbesar berasal dari penggunaan cache objek. Jika Anda menggunakan solusi cache memori persisten seperti XCache atau memcached atau APC atau sesuatu seperti itu, dan memiliki plugin yang dapat mengikat cache objek Anda ke sana (W3 Total Cache, misalnya), maka seluruh cache objek Anda disimpan dalam memori cepat sudah. Dalam hal ini, ada nol query yang diperlukan untuk mengambil data Anda; itu sudah ada dalam memori. Caching objek yang persisten luar biasa dalam banyak hal.
Dengan kata lain, kueri Anda mungkin memuat dan memuat lebih lambat daripada menggunakan kueri yang tepat dan solusi memori persisten sederhana. Gunakan yang normal
WP_Query
. Selamatkan diri Anda sedikit usaha.Tambahan:
update_meta_cache()
cerdas, BTW. Itu tidak akan mengambil informasi meta untuk posting yang sudah memiliki informasi meta yang di-cache. Tidak mendapatkan meta yang sama dua kali, pada dasarnya. Sangat efisien.Tambahan tambahan: "Berikan sebanyak mungkin pekerjaan ke basis data." ... Tidak, ini web. Aturan yang berbeda berlaku. Secara umum, Anda selalu ingin memberikan sesedikit mungkin pekerjaan ke database, jika layak. Database lambat atau tidak terkonfigurasi dengan baik (jika Anda tidak mengonfigurasinya secara spesifik, Anda dapat bertaruh uang baik bahwa ini benar). Seringkali mereka dibagi di antara banyak situs, dan kelebihan beban sampai batas tertentu. Biasanya Anda memiliki lebih banyak server web daripada database. Secara umum, Anda hanya ingin mendapatkan data yang Anda inginkan dari DB secepat dan sesederhana mungkin, kemudian lakukan penyortiran dengan menggunakan kode sisi-server-web. Sebagai prinsip umum, tentu saja, kasus yang berbeda semuanya berbeda.
sumber
Saya akan merekomendasikan kueri pivot. Menggunakan contoh Anda:
sumber
Saya telah menemukan sebuah kasus di mana saya ingin juga ingin cepat mengambil banyak posting dengan informasi meta yang terkait. Saya perlu mengambil posting O (2000).
Saya mencoba menggunakan saran Otto - menjalankan WP_Query :: permintaan untuk semua posting, dan kemudian mengulang dan menjalankan get_post_custom untuk setiap posting. Ini membutuhkan, rata-rata, sekitar 3 detik untuk selesai .
Saya kemudian mencoba permintaan pivot Ethan (meskipun saya tidak suka harus secara manual meminta setiap meta_key yang saya minati). Saya masih harus mengulang semua posting yang diambil untuk membatalkan pengunaan meta_value. Ini membutuhkan, rata-rata, sekitar 1,3 detik untuk selesai .
Saya kemudian mencoba menggunakan fungsi GROUP_CONCAT, dan menemukan hasil terbaik. Ini kodenya:
Ini memakan waktu rata-rata 0,7 detik . Itu sekitar seperempat waktu dari solusi get_post_custom (WP) dan sekitar setengah dari solusi kueri pivot.
Mungkin ini akan menarik bagi seseorang.
sumber
Saya menemukan diri saya dalam situasi dimana saya perlu melakukan tugas ini untuk akhirnya membuat dokumen CSV, saya akhirnya bekerja secara langsung dengan mysql untuk melakukan ini. Kode saya bergabung dengan posting dan tabel meta untuk mengambil informasi harga woocommerce, solusi yang diposting sebelumnya mengharuskan saya menggunakan alias tabel di sql untuk bekerja dengan baik.
Berhati-hatilah, woocommerce membuat 300.000 baris di tabel meta saya, jadi itu sangat besar, dan karenanya sangat lambat.
sumber
TANPA SQL VERSI:
Dapatkan semua posting dan semua nilai meta (meta) mereka tanpa SQL:
Katakanlah Anda memiliki daftar ID kiriman yang disimpan sebagai larik ID, kira-kira seperti itu
Sekarang mendapatkan semua posting dan semua meta dalam 1 kueri tidak mungkin tanpa menggunakan setidaknya sedikit SQL, jadi kita harus melakukan 2 query (masih hanya 2):
1. Dapatkan semua posting (menggunakan WP_Query )
(Jangan lupa menelepon
wp_reset_postdata();
jika Anda melakukan "putaran" sesudahnya;))2. Perbarui meta cache
Untuk mendapatkan data meta cukup gunakan standar
get_post_meta()
yang, seperti yang ditunjukkan @Otto:lihat ke cache terlebih dahulu :)
Catatan: Jika Anda tidak benar-benar membutuhkan data lain dari pos (seperti judul, konten, ...) Anda dapat melakukannya hanya 2. :-)
sumber
menggunakan bentuk solusi trevor dan memodifikasinya untuk bekerja dengan SQL bersarang. Ini tidak diuji.
sumber
Saya berlari ke masalah beberapa bidang meta nilai juga. Masalahnya adalah dengan WordPress itu sendiri. Lihat di wp-include / meta.php. Cari baris ini:
Masalahnya dengan pernyataan CAST. Dalam kueri untuk nilai meta, variabel $ meta_type disetel ke CHAR. Saya tidak tahu detail tentang bagaimana CASTing nilai ke CHAR mempengaruhi string serial, tetapi untuk memperbaikinya, Anda bisa menghapus para pemain sehingga SQL terlihat seperti ini:
Sekarang, meskipun itu berhasil, Anda mucking dengan internal WordPress, sehingga hal-hal lain mungkin rusak, dan itu bukan perbaikan permanen, dengan asumsi Anda harus meng-upgrade WordPress.
Cara saya memperbaikinya adalah dengan menyalin SQL yang dihasilkan oleh WordPress untuk kueri meta yang saya inginkan dan kemudian menulis beberapa PHP untuk menempel pada pernyataan AND tambahan untuk meta_values yang saya cari dan gunakan $ wpdb-> get_results ($ sql ) untuk hasil akhir. Meretas, tetapi berhasil.
sumber
get_meta_sql
filter yang mengikuti baris ini tentu saja lebih baik daripada meretas kode inti.