Bir listeyi önce meta anahtarla (varsa) sıralamak ve kalan anahtarları başlığa göre sıralanmış meta anahtar olmadan göstermek için sorgulama


22

Terime bağlı öğelerin bir yayın tarihine (özel tarih alanı) göre sıralanmasını istediğimiz özel bir sınıflandırma terim sayfası şablonu üzerinde çalışıyorum - ve aynı günde birden çok öğe varsa (YYYY-AA- DD) daha sonra bunları başlığa göre sıralayın ve son olarak özel alan doldurulmamışsa (eski öğeler) başlığa göre sıralayın.

Bu yüzden, bir WP_query ile yüz farklı şekilde denedim ve sonuçların çoğunu istediğim gibi döndürür - ancak bu durumda sadece public__tete meta_keyine sahip öğeleri döndürür. Diğer tüm öğeler yok sayılıyor ve görüntülenmiyor. "Veya" ilişkisini kullanarak bir meta_query denedim ve publication_date EXISTS ve EXISTS olarak karşılaştırıldı, ama bu benim için 0 sonuç döndürdü.

Ayrıca, site 3.5.2 hala çalışıyor ve yükseltmek istemiyorlar.

Publication_date özel alanı doğru sırada görüntülenen yayınları bana gönderen en son sorgum:

$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',
));

Ben de wpdb kullanarak ve bir SQL sorgusu çalıştırmayı denedim, ama gerçekten nasıl bunu yapmak istediğimi gerçekleştirmek için emin değilim. Birisi bana yardımcı olabilir harika olurdu!

Şimdiden teşekkürler.


Meta_query yaklaşımı işe yaramadı, ancak daha sonra meta_key ayarlanmadan meta_query ile meta değeri sipariş edemezsiniz.
sanchothefat

Sanırım yaşadığım sorun bu. Sonunda çalışan bir meta sorgu aldım: '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' ) ),ama sipariş çalışmıyor: \
CSSgirl

Evet, sipariş maalesef tax_query dışında ayarlanan meta_key'e dayanır. Aşağıdaki cevabım yardımcı olabilir.
sanchothefat

Yanıtlar:


19

Yardımınız için herkese teşekkürler!

Sonunda aşağıdaki sorgu bana istediğim sonuçları elde etti - bu mesajlar ilk olarak "publication_date" özel alanına göre göstermek ve sıralamak - tarihe göre sıralama ve aynı tarihin birden fazla olması durumunda (örneğin, 4 işaretli) Haziran 2013), bunları başlığa göre sıralar. Ardından, Yayınlanma Tarihi'nin doldurulmuş olduğu tüm yayınlar çalıştırıldıktan sonra, geri kalan yayınlar alfabetik olarak başlığa göre tekrar çevrilecektir.

Bu bana aynı sorguda ayarlanan sonuçları alır ve sayfalandırmamı korur:

$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',
));

1
Güzel. meta_queryAynı anahtar üzerinde iki tane çalıştırmayı hiç düşünmemiştim !
GhostToast

5
Benim için (WordPress 4.1.1 kullanarak), meta_keyotomatik olarak ayarlarsam bile içermez NOT EXISTS. Umarım yanlış bir şey yapıyorum.
Ryan Taylor

1
@RyanTaylor burada aynı - meta_key, bunun çalışması için sorguda ayarlanmamalıdır, ancak meta anahtar ayarlanmamış olsa bile meta değerine göre doğru bir şekilde sıralandığı görülür.
jammypeach

2
Yukarıdaki yorumlarda olduğu gibi, WP 4.1+ için kaldırın veya yorum yapın 'meta_key' => 'publication_date',.
MikeiLL

7

Birkaç yıl sonra, CSSGirl tarafından gönderilen kod benim için çalışmadı çünkü meta anahtarı olmayan veya meta anahtarı boş olan bazı yayınlar vardı, bu yüzden tüm yayınları tarihe göre sıralamak için yapmam gereken şey buydu ve önce meta anahtar değeri görüntüleyenleri göster:

$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' ),
);

1

2 ayrı döngü yapmanız gerektiğini düşünüyorum. İlk döngüde bulunan tüm yayınları yakalayabilir ve ikincil döngüden kolayca hariç tutabilirsiniz:

$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,
);

Sonra ikinci döngünüzü çalıştırın.


Bunu şimdi deniyorum, teşekkürler. Çalışıp çalışmadığını size bildirir!
CSSgirl

1
Bu işe yaradı - ama sayfa numaralandırmayı kırdı - bunun nasıl işe yarayacağına dair bir fikrin var mı? İşte şu şekilde görünüyor: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. Aklıma gelen değil.
GhostToast

1

Publication_date meta anahtarını boş bir değere sahip her yazı için zorunlu kılmamanızın bir nedeni var mı?

Böylece save_posteyleminizde, $_POSTdeğer boş olsun ya da olmasın meta anahtarı eklersiniz / güncellersiniz .

Eski yayınlarınızın üzerinden döngü oluşturmak ve anahtarı boş bir değere eklemek için bir güncelleme komut dosyası çalıştırmanız gerekir:

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;
}

Http://example.com/wp-admin/?update_old_posts adresine giderek çalıştırın.

Sonra sahip olduğunuz sorguyu kullanabilirsiniz. Farklı yönlerde farklı sütunlara göre sipariş vermenizi sağlamak için ekstra bir filtre eklemek isteyebilirsiniz, artan sırayla ve başlığa göre artan sırada sıralamak bana mantıklı olacaktır.

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;
}

Hmm, bunu düşünmedim. Bunu deneyeceğim ve nasıl gittiğini göreceğim, teşekkürler!
CSSgirl

0

Özel bir nerede cümlesi oluşturdum. $wp_query->requestAna döngüden hemen önce test ettim , SQL'i gerçekten iyi bilmiyorum, ama bu işler işe yaramış gibi görünüyordu.

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;
}

Alternatif olarak, ayarlayabilirsiniz compareiçin 'EXISTS've add_trending_where hattı değiştiremezsiniz $where .= " OR ($wpdb->postmeta.post_id IS NULL)";. Ardından, anahtarın değerini yalnızca tek bir yerde değiştirmeniz gerekir. Yine, $wp_query->requestbunu daha iyi anlamak ya da değiştirmek istiyorsanız yankılayın ve oynayın.

EDIT: Ben sadece meta_keysorgu ayarlanırsa bu işe yaramadı fark ettim . $query->set('meta_key', NULL);Gerekirse kullanabilirsiniz .

EDIT 2: Yukarıdaki yöntemle bu çalışmayı aldım. Nedense ilk başta değildi (belki meta_key ayarlandı ... Bilmiyorum).

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'));
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.