Saya telah memodifikasi pencarian WP bawaan menggunakan pre_get_posts
filter, yang memungkinkan pengguna untuk mengurutkan posting (termasuk banyak jenis posting khusus) berdasarkan bidang yang berbeda.
Masalah yang saya alami adalah ketika saya memberi tahu WP untuk mengurutkan berdasarkan nilai meta, itu akan mengecualikan semua posting yang tidak memiliki set nilai meta itu. Ini menyebabkan jumlah hasil berubah jika Anda mengubah pengurutan dari katakan "Harga" ke "Tanggal" karena "Posting" tidak memiliki set "Harga" tetapi "Item" lakukan.
Ini bukan yang saya inginkan, jadi saya ingin tahu apakah ada cara untuk memasukkan SEMUA posting - bahkan yang tidak memiliki nilai meta yang saya sortir - dan menempatkan yang tanpa nilai terakhir.
Saya tahu cara menyortir lebih dari satu bidang tetapi itu tidak membantu.
Terima kasih
Sepertinya saya bukan satu-satunya dengan pertanyaan ini: Cara untuk memasukkan posting baik dengan & tanpa meta_key tertentu dalam args untuk wp_query? tapi tidak ada solusi di sana.
Memperbarui
Saya sudah mencoba jawabannya tetapi tidak yakin apakah saya mengerti dengan benar, inilah yang saya miliki sekarang:
<?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');
}
Nilai meta adalah angka (digunakan untuk menyimpan harga seperti namanya)
Perbarui 2
Saya sudah berkomentar soal pesanan dan yang saya miliki sekarang adalah ini:
<?php
$qry->set('meta_query', array(array(
'key' => 'item_price',
'value' => '',
'compare' => 'NOT EXISTS'
)));
Dengan kode ini kueri tampaknya mengembalikan semua posting yang tidak memiliki item_price
kunci dan tidak ada posting yang memilikinya. Yaitu masalah sekarang terbalik.
Jika saya menambahkan kode-urutan juga saya mendapatkan 0 hasil.
Sunting: ... tiga tahun kemudian ... : PI mengalami masalah ini lagi. Saya mencoba semua jawaban yang diberikan dan tidak ada yang berhasil. Tidak yakin mengapa beberapa orang tampaknya berpikir mereka bekerja tetapi setidaknya mereka tidak bekerja untuk saya.
Solusi yang akhirnya saya gunakan adalah save_post
filter - memastikan semua posting memiliki bidang khusus yang ingin saya urutkan. Agak menyebalkan saya harus melakukannya, tetapi selama Anda melakukannya sejak dini, Anda mungkin tidak akan memiliki masalah.
Dalam hal ini saya sedang membangun "penghitung tampilan" pada posting dan ingin pengguna dapat mengurutkan pada posting yang paling banyak dibaca. Sekali lagi, postingan yang belum pernah dilihat (saya rasa itu tidak mungkin - tetapi masih) menghilang ketika mengurutkan pada jumlah tampilan. Saya menambahkan sedikit kode ini untuk memastikan semua posting memiliki jumlah tampilan:
add_action('save_post', function ($postId) {
add_post_meta($postId, '_sleek_view_count', 0, true);
});
sumber
meta_query
dantax_query
yang selalu merupakanarray( array() )
karena mereka menggabungkan beberapa array. Kedua - seperti yang disebutkan dalam jawaban saya - Anda harus menggunakanmeta_value_num
angka. Mungkin diperlukan untuk benar-benar mendefinisikanmeta_value_num
(lihatWP_Query
entri halaman -Codex). Terakhir, itu tidak masuk akal untukorder
masukASC
danDESC
arah. Itu tidak mungkin. Pembatas ruang hanya berfungsi untukorderby
dan Anda tidak bisa mengatakannya untuk mengurutkan yang pertamaASC
dan yang keduaDESC
. Itulah gunanyaposts_clauses
filter.meta_value_num
entri Anda adalah bilangan real . Terlihat terlalu sering bahwa seseorang menyatakan bahwa itu adalah angka, tetapi sebenarnya menyimpannya sebagai string dalam database.ASC DESC
adalah agar ia bisa mengurutkan dimeta_value
dalamASC
dan didate
dalamDESC
, sejauh yang saya tahu itu berhasil.Jawaban:
Ada dua solusi yang memungkinkan untuk ini:
1. Semua posting memiliki meta
Solusi terbaik yang saya temukan di sini adalah memberikan sisa barang / produk harga barang 0. Anda dapat melakukan ini secara manual, atau loop melalui semua posting dan jika harga kosong maka perbarui.
Untuk membuat ini dapat dikelola di masa mendatang, Anda dapat menghubungkan
save_post
dan memberi mereka nilai saat pertama kali ditambahkan (hanya jika kosong).2. Banyak Pertanyaan
Anda dapat menjalankan kueri pertama saat melakukan dan menyimpan ID kiriman yang dikembalikan. Anda kemudian dapat menjalankan kueri lain untuk semua posting dan tanggal orderby, tidak termasuk ID yang kembali dari kueri pertama.
Anda kemudian dapat mencetak dua hasil secara terpisah dan Anda akan mendapatkan hasil yang diinginkan.
sumber
save_post
metode ini (Saya telah memperbarui pertanyaan saya dengan kode yang saya gunakan).Easy Peasy, baru diuji 2018, menggunakan dalam produksi saat ini.
Ini memeriksa semua item dengan dan tanpa kunci meta, tanpa nilai yang ditentukan. meta query menyediakan kunci untuk orderby dengan andal. Sudah diuji. Namun saya tidak yakin bagaimana cara kerjanya ketika kueri meta menggunakan beberapa kunci.
Contoh praktis
Ini akan memesan posting secara
custom_meta_key
default, dan tidak akan mengabaikan posting tanpa nilai untuk kunci itu.sumber
custom_meta_key
dan mendapatkan postingan yang tidak dimilikicustom_meta_key
. Jangan ragu untuk memasukkan contoh kerja aktual dengan penyortiran.$query->set( 'orderby', 'meta_value title' );
(Pesan berdasarkan nilai meta, lalu dengan judul saat beberapa pos memiliki nilai yang sama untuk kunci meta). Ini harus dilakukan dipre_get_posts
hook, menggunakan$query
variabel yang dikirimkan . Perlu diingat pertanyaan yang diajukan adalah bagaimana cara memesan berdasarkan nilai meta, sementara tidak mengabaikan posting yang tidak memiliki nilai untuk kunci meta itu.get_posts()
panggilan khusus untuk mendorong posting dengan_featured
meta ke atas, lalu pesan berdasarkan tanggal setelah itu. Terima kasih!Metode ini akan mengembalikan semua posting termasuk yang dengan dan tanpa yang diminta
meta_key
, tetapi akan melakukan hal-hal aneh ketika memesan.Saya menemukan ini dengan mengutak-atik semua jawaban yang berbeda untuk pertanyaan ini dan menganalisis SQL yang dihasilkan melalui trial and error. Tampaknya pengaturan
array('meta_query' => array('relation' => 'OR'))
output yang sesuaiLEFT JOIN
bukanINNER JOIN
yang diperlukan untuk memasukkan posting yang kehilangan metadata. Menentukan klausaNOT EXISTS
mencegahWHERE
penyaringan posting yang tidak memiliki bidang meta. Untuk iniWP_Query
, SQL yang dihasilkan adalah (indentasi / baris baru ditambahkan):Hasilnya adalah daftar semua posting dengan meta_value
item_price
dan mereka yang hilangitem_price
. Semua pos denganitem_price
akan dipesan dengan benar relatif satu sama lain, tetapi pos yang hilangitem_price
akan menggunakan beberapa nilai meta acak lainnya (misalnya,_edit_last
yang tampaknya1
cukup sering di database saya atau beberapa metadata wordpress internal lain yang sepenuhnya arbitrer) untuk ituwp_postmeta.meta_value
dalam yangORDER BY
klausa. Jadi, sementara metode ini dekat dan mungkin berfungsi untuk data tertentu, itu rusak. Jadi, yang bisa saya katakan adalah, jikaitem_price
nilai Anda kebetulan tidak bertentangan dengan bidang meta acak yang dipilih MySQL untuk pos yang hilangitem_price
, ini mungkin bekerja dengan baik untuk Anda. Jika semua yang Anda butuhkan adalah jaminan bahwa posting Anda denganitem_price
dipesan dengan benar relatif satu sama lain tanpa memperhatikan urutan posting lain, mungkin OK. Tapi saya pikir ini hanya kekurangan di wordpress. Tolong koreksi saya, saya harap saya salah dan ada cara untuk mengatasi ini ;-).Tampaknya untuk
INNER JOIN wp_postmeta
, MySQL memilih baris acak dari antara beberapapostmeta
baris yang terkait dengan pos ketikameta_key
ada yang hilang dari pos yang diberikan. Dari perspektif SQL, kita perlu mencari tahu bagaimana cara memberitahu wordpress ke outputORDER BY mt1.meta_value
. Kolom ini benarNULL
ketika permintaan kamimeta_key
tidak ada, tidak sepertiwp_postmeta.meta_value
. Jika kita bisa melakukan itu, SQL akan mengurutkan iniNULL
(entri yang hilang) sebelum nilai lain, memberikan kita urutan yang jelas: pertama datang semua posting yang hilang bidang postmeta tertentu, kedua datang tulisan yang memiliki bidang. Tapi itu adalah keseluruhan masalahnya:'orderby' => 'meta_value'
hanya bisa merujuk'meta_key' => 'item_price'
dan yang tidak berubahwp_postmeta
selalu merupakan,INNER JOIN
bukanLEFT JOIN
makna,wp_postmeta.meta_value
danwp_postmeta.meta_key
bisatidak akan pernahNULL
.Jadi saya kira saya harus mengatakan bahwa ini tidak mungkin dengan built-in wordpress
WP_Query
seperti yang sekarang didokumentasikan (di wordpress-3.9.1). Mengganggu. Jadi jika Anda benar-benar membutuhkan ini untuk bekerja dengan benar, Anda mungkin perlu menghubungkan ke wordpress di tempat lain dan memodifikasi SQL yang dihasilkan secara langsung .sumber
Saya rasa saya punya solusi.
Anda dapat menggunakan dua
meta_key
s, satu yang dimiliki semua pos(like "_thumbnail_id")
, dan yangmeta_key
ingin Anda gunakan sebagai filter.Jadi argumen Anda:
sumber
'value' => '',
juga perbandingan kedua harusNOT EXISTS
dan instruksi set terakhir tidak diperlukanMasalah yang harus dihadapi semua orang di sini adalah dengan urutan meta queries. Untuk mengurutkan dengan benar, Anda harus memasukkan kueri "BUKAN ADA" sebelum kueri "ADA".
Alasannya adalah karena WordPress menggunakan meta_value dari pernyataan "LEFT JOIN" terakhir di klausa "ORDER BY".
Sebagai contoh:
sumber
Jika cocok, Anda dapat menambahkan nilai meta default setiap kali posting disimpan atau diperbarui, jika nilai meta tidak ada.
Jika Anda menggunakan jenis posting khusus, ganti
add_action('save_post', 'addDefaultMetaValue');
denganadd_action('save_post_{post_type}', 'addDefaultMetaValue');
misalnyaadd_action('save_post_product', 'addDefaultMetaValue');
sumber
Saya memiliki masalah sendiri untuk nilai meta numerik dan menunjukkan bahwa urutan kueri juga penting. Bagi saya
NOT EXISTS
kueri harus menjadi yang pertama.Contoh:
Juga penting untuk mendapatkan arah yang benar untuk nilai numerik adalah umum yang
’orderby’
harus diatur’meta_value_num’
. Kalau tidak, Anda memiliki hasil aneh untuk nilai numerik, misalnya:1, 2, 20, 21, 3, 4, 5…
Dari pada:
1, 2, 3, 4, 5… 20, 21
sumber
Saya juga mengalami masalah serupa dan solusi berikut membantu saya:
Saya menemukan deskripsi di WordPress Codex dengan judul " 'orderby' dengan beberapa 'meta_key's ": https://codex.wordpress.org/Class_Reference/WP_Query#Order_.26_Orderby_Parameters
sumber
Ada kemungkinan
orderby
nilaimeta_value
untuk itu.Jika Anda mendapat nilai numerik, gunakan
meta_value_num
saja.Penafian: Ini tidak diuji, tetapi harus bekerja. Intinya adalah bahwa Anda perlu menentukan nilai
meta_key
dankey
nilai Anda. Jika tidak, Anda tidak dapat membandingkan dengan nilai yang tidak ada, yang seharusnya memungkinkan untuk menanyakan kedua jenis posting. Ini semacam hack-ish, tapi selama itu berhasil ...sumber
'your_keys_name'
dan'your_meta_key'
keduanya harus string yang sama, bukannya berbeda, jika tidak, sepertinya Anda telah salah paham pertanyaannya. Kedua, saya menguji ini pada pengaturan lokal saya dan mengecualikan posting mana pun kunci ada (melaluimeta_query
) dan mengecualikan setiap posting di mana kunci hilang (melaluimeta_key
) sehingga tidak ada posting yang ditampilkan. Namun, jawaban ini adalah langkah menuju sesuatu yang kata-kata setidaknya ;-).'relation' => 'OR'
untukmeta_query
. Hal aneh o_o.Saya pikir apa yang @kaiser coba lakukan adalah memberi tahu kueri untuk mengembalikan semua posting yang memiliki kunci meta dengan menerapkan semacam dummy di mana syaratnya untuk tidak menyaring posting-posting itu. Jadi, jika Anda tahu semua nilai yang dapat diambil bidang kustom Anda adalah x, y, z Anda bisa mengatakan "WHERE meta_key IN (x, y, z) " tetapi idenya adalah Anda dapat menghindari masalah itu bersama-sama dengan mengatakan ! = (' ') :
Juga tidak diuji tetapi rasanya layak untuk dicoba :-).
sumber
Saya akhirnya menyelesaikan ini dengan sedikit hack (IMHO), tapi itu berhasil bagi saya dalam kasus saya.
Anda dapat menghubungkan ke filter posts_join_paged dan posts_orderby untuk memperbarui gabung dan memesan string. Ini akan memungkinkan Anda untuk memesan dengan apa pun yang Anda inginkan selama Anda bergabung terlebih dahulu daripada WP_Query dengan asumsi bahwa bidang tersebut harus ada untuk pos tertentu. Anda kemudian dapat menghapus
meta_key
,orderby
dan `perintah dari args WP_Query Anda.Di bawah ini adalah contohnya. Di bagian atas setiap fungsi saya harus melarikan diri untuk kasus-kasus tertentu karena akan menambahkan ini ke semua yang menggunakan WP_Query. Anda mungkin perlu memodifikasinya agar sesuai dengan kebutuhan khusus Anda.
Dokumentasi pada kedua filter ini sayangnya kurang begitu ... semoga berhasil! :)
sumber
cast(my_custom_meta_key.meta_value as unsigned) DESC
harus melakukan trik ...$orderby_statement = "cast(my_custom_meta_key.meta_value as unsigned) DESC";
bekerja dengan baik.Solusi ini bekerja untuk saya:
Namun, solusi ini pertama-tama menunjukkan catatan dengan meta_value nol. Solusi lain ini menunjukkan urutan dan null ASC pada akhirnya:
sumber