Permintaan untuk mengurutkan daftar berdasarkan kunci meta terlebih dahulu (jika ada), dan tampilkan posting yang tersisa tanpa kunci meta yang diurutkan berdasarkan judul

22

Saya sedang mengerjakan templat laman istilah taksonomi khusus tempat kami menginginkan item yang terhubung ke istilah diurutkan berdasarkan tanggal publikasi (bidang tanggal khusus) - dan jika ada beberapa item pada hari yang sama (diformat seperti YYYY-MM- DD) untuk kemudian mengurutkan berdasarkan judul, dan akhirnya mengurutkan berdasarkan judul jika bidang khusus belum diisi (item yang lebih lama).

Jadi, saya mencobanya ratusan cara berbeda dengan WP_query dan itu mengembalikan sebagian besar hasil seperti yang saya inginkan - tetapi dalam kasus ini hanya mengembalikan item yang memiliki meta_key dari publishing_date. Semua item lainnya diabaikan dan tidak ditampilkan. Saya mencoba meta_query menggunakan relasi "atau" dan membandingkan publikasi_date sebagai EXIS dan NOT EXISTS, tetapi hasilnya 0 untuk saya.

Juga, situs masih menjalankan 3.5.2 dan mereka tidak ingin memperbarui.

Inilah kueri saya yang paling baru yang memberi saya pos-pos yang memiliki bidang kustom publishing_date ditampilkan dalam urutan yang benar:

$term = get_queried_object(); // find the term of the taxonomy page we are on
$wp_query = new WP_Query( array(
'post_type' => 'resource',
'tax_query' => array(
    array(
        'taxonomy' => 'resource_types',
        'field' => 'slug',
        'terms' => $term->name,
    )), 

'meta_key' => 'publication_date',
'orderby' => 'meta_value_num',
'order' => 'DESC',
'paged' => $paged,
'posts_per_page' => '10',
));

Saya juga mencoba menggunakan wpdb dan menjalankan query SQL, tetapi saya benar-benar tidak yakin bagaimana mencapai apa yang ingin saya lakukan itu. Jika seseorang bisa membantu saya, itu akan luar biasa!

Terima kasih sebelumnya.

CSSgirl
sumber
Terkejut pendekatan meta_query tidak berhasil, tetapi sekali lagi Anda tidak bisa memesan nilai meta dengan meta_query tanpa memiliki set meta_key.
sanchothefat
Saya pikir itulah masalah yang saya alami. Saya akhirnya mendapatkan kueri meta yang berfungsi: 'meta_query' => array( 'relation' => 'OR', array( //check to see if date has been filled out 'key' => 'publication_date', 'compare' => '!=', 'value' => date('Y-m-d'), ), array( //if no date has been added show these posts too 'key' => 'publication_date', 'value' => date('Y-m-d'), 'compare' => 'NOT EXISTS' ) ),tetapi pemesanannya tidak berfungsi: \
CSSgirl
ya, pemesanan bergantung pada meta_key yang ditetapkan di luar tax_query sayangnya. Jawaban saya di bawah ini mungkin membantu.
sanchothefat

Jawaban:

19

Terima kasih semuanya atas bantuan Anda!

Pada akhirnya, kueri di bawah memberi saya hasil yang saya inginkan - yaitu untuk menampilkan dan mengurutkan posting berdasarkan bidang khusus "publishing_date" terlebih dahulu - mengurutkan berdasarkan tanggal, dan jika ada beberapa dari tanggal yang sama (misalnya, 4 ditandai Juni 2013), itu akan mengurutkan berdasarkan judul. Kemudian, setelah dijalankan melalui semua posting yang memiliki Tanggal Publikasi diisi di dalamnya akan mengulang lagi posting yang tersisa, menurut abjad menurut judul.

Ini membuat saya hasil yang ditetapkan dalam permintaan yang sama, dan membuat pagination saya:

$term = get_queried_object();
the_post();
$wp_query = new WP_Query( array(
'post_type' => 'resource',
    'tax_query' => array(
        array(
            'taxonomy' => 'resource_types',
            'field' => 'slug',
            'terms' => $term->name,
        )),
 'meta_query' => array(
       'relation' => 'OR',
        array( //check to see if date has been filled out
                'key' => 'publication_date',
                'compare' => '=',
                'value' => date('Y-m-d')
            ),
          array( //if no date has been added show these posts too
                'key' => 'publication_date',
                'value' => date('Y-m-d'),
                'compare' => 'NOT EXISTS'
            )
        ),
'meta_key' => 'publication_date',
'orderby' => 'meta_value title',
'order' => 'ASC',
'paged' => $paged,
'posts_per_page' => '10',
));
CSSgirl
sumber
1
Bagus. Saya tidak pernah berpikir untuk menjalankan dua meta_querypada kunci yang sama!
GhostToast
5
Bagi saya (menggunakan WordPress 4.1.1), jika saya atur meta_keysecara otomatis tidak termasuk bahkan dengan NOT EXISTS. Saya sangat berharap saya melakukan sesuatu yang salah.
Ryan Taylor
1
@RyanTaylor sama di sini - meta_key tidak boleh diatur dalam kueri agar ini berfungsi, tetapi tampaknya memesan dengan benar berdasarkan nilai meta bahkan ketika kunci meta tidak disetel.
jammypeach
2
Seperti komentar di atas, untuk WP 4.1+ hapus atau komentari 'meta_key' => 'publication_date',.
MikeiLL
7

Beberapa tahun kemudian, kode yang diposting oleh CSSGirl tidak berfungsi untuk saya karena ada beberapa posting yang tidak memiliki kunci meta atau kunci meta kosong jadi ini yang harus saya lakukan untuk memiliki semua posting yang dipesan berdasarkan tanggal dan tunjukkan yang dengan tampilan nilai kunci meta terlebih dahulu:

$args          = array(
'post_type'   => $type,
'post_status' => 'publish',
'nopaging'    => TRUE,
'meta_query'  => array(
    'relation' => 'OR',
    array(
        'key'     => $meta_key,
        'compare' => 'NOT EXISTS',
    ),
    array(
        'relation' => 'OR',
        array(
            'key'   => $meta_key,
            'value' => 'on',
        ),
        array(
            'key'     => $meta_key,
            'value'   => 'on',
            'compare' => '!=',
        ),
    ),
),
'orderby'     => array( 'meta_value' => 'DESC', 'date' => 'DESC' ),
);
Ciprian Tepes
sumber
1

Saya pikir Anda harus melakukan 2 loop terpisah. Anda dapat menangkap semua pos yang ditemukan di loop pertama dan cukup mengecualikannya dari loop sekunder:

$found_posts = array();
while($loop->have_posts()): $loop->the_post();
    // loop stuff
    $found_posts[] = get_the_id();
endwhile;

wp_reset_query();

$args = array(
    // other args
    'post__not_in' => $found_posts,
);

Kemudian jalankan loop kedua Anda.

GhostToast
sumber
Coba ini sekarang, terima kasih. Akan memberi tahu Anda jika berhasil!
CSSgirl
1
ini bekerja - tetapi itu merusak pagination - tahu bagaimana cara ini berfungsi? Begini tampilannya sekarang:echo paginate_links( array( 'base' => str_replace( $big, '%#%', esc_url( get_pagenum_link( $big ) ) ), 'format' => '?page=%#%', 'current' => max( 1, get_query_var('paged') ), 'total' => $publication_query->max_num_pages, 'prev_text' => __('Previous |'), 'next_text' => __('| Next'), ) );
CSSgirl
Hmm. Bukannya aku bisa memikirkannya.
GhostToast
1

Apakah ada alasan Anda tidak dapat menerapkan kunci meta publishing_date yang ada untuk setiap posting hanya dengan nilai kosong?

Jadi dalam save_posttindakan Anda, Anda akan menambahkan / memperbarui kunci meta apakah $_POSTnilainya kosong atau tidak.

Anda harus menjalankan skrip pembaruan untuk mengulangi posting lama Anda dan menambahkan kunci dengan nilai kosong misalnya:

add_action( 'admin_init', 'update_old_posts' );
function update_old_posts() {
    if ( ! isset( $_GET[ 'update_old_posts' ] ) )
         return;

    foreach( get_posts() as $post ) {
        if ( false === get_post_meta( $post->ID, 'publication_date', true ) ) {
             update_post_meta( $post->ID, 'publication_date', '' );
             echo "Updated {$post->post_title} <br />";
        }
    }

    die;
}

Jalankan dengan menjelajah ke http://example.com/wp-admin/?update_old_posts

Kemudian Anda dapat menggunakan kueri yang sama seperti yang Anda miliki. Anda mungkin ingin menambahkan filter tambahan untuk memungkinkan Anda memesan dengan kolom yang berbeda di arah yang berbeda, masuk akal bagi saya untuk mengurutkan berdasarkan tanggal dalam urutan menurun dan judul dalam urutan naik.

add_filter( 'posts_orderby', 'multicolumn_orderby', 10, 2 );
function multicolumn_orderby( $orderby, $query ) {
    global $wpdb;

    // check it's the right query
    if ( $query->get( 'meta_key' ) == 'publication_date' ) {
         $orderby = "$wpdb->postmeta.meta_value+0 DESC, $wpdb->posts.post_title ASC";
    }

    return $orderby;
}
sanchothefat
sumber
Hmm, saya tidak memikirkan itu. Saya akan mencobanya dan melihat bagaimana kelanjutannya, terima kasih!
CSSgirl
0

Saya membuat klausa tempat kustom. Saya mengujinya menggunakan $wp_query->requesttepat sebelum loop utama saya, saya tidak benar-benar tahu SQL itu dengan baik, tetapi ini tampaknya membuat semuanya berfungsi.

add_action('pre_get_posts', 'add_trending_sort', 11, 1);
function add_trending_sort($query){
  if(!$query->is_main_query())
    return;

  //Overwrite query arguments
  $query->set('meta_query', array(
    array(
      'key' => 'TRENDING',
      //'value' => 'asdfasdf',//may need a value for older versions of WordPress
      'compare' => 'NOT EXISTS',
    )
  ));
  $query->set('orderby', 'meta_value_num date');
  $query->set('order', 'DESC');
}

add_filter('posts_where', 'add_trending_where');
function add_trending_where($where = ''){
  global $wpdb, $wp_query;
  if(!$wp_query->is_main_query())//Not sure if this really works.  Should be OK
    return $where;

  $where .= " OR ( $wpdb->postmeta.meta_key = 'TRENDING' )";

  // Don't run this twice
  remove_filter('posts_where', 'add_trending_where');

  return $where;
}

Atau, Anda bisa mengatur compareuntuk 'EXISTS'dan mengubah baris di add_trending_where untuk $where .= " OR ($wpdb->postmeta.post_id IS NULL)";. Maka Anda hanya perlu mengubah nilai kunci di satu tempat. Sekali lagi, gema $wp_query->requestdan mainkan jika Anda ingin memahami ini lebih baik atau men-tweak itu.

EDIT: Saya baru menyadari ini tidak berfungsi jika meta_keydiatur pada permintaan. Anda dapat menggunakan $query->set('meta_key', NULL);jika Anda harus.

EDIT 2: Saya mendapatkan ini berfungsi dengan metode di atas. Untuk beberapa alasan itu bukan pada awalnya (mungkin meta_key diatur ... saya tidak tahu).

add_action('pre_get_posts', 'add_trending_sort', 11, 1);
function add_trending_sort($query){
  // Bail if not the main "hidden" query, as opposed to a 'new WP_Query()' call
  if(!$query->is_main_query())
    return;

  // Set meta_query to get shares for orderby, and also get non-shared content.
  $query->set('meta_query', array(
    'relation' => 'OR',
    array(
      'key' => 'TRENDING',
      'compare' => 'NOT EXISTS',
    ),
    array(
      'key' => 'TRENDING',
      'compare' => 'EXISTS',
    )
  ));
  //$query->set('meta_key', NULL);
  $query->set('orderby', array('meta_value_num' => 'DESC', 'date' => 'DESC'));
}
Ryan Taylor
sumber