Truy vấn để sắp xếp danh sách theo khóa meta trước (nếu nó tồn tại) và hiển thị các bài đăng còn lại mà không có khóa meta được sắp xếp theo tiêu đề


22

Tôi đang làm việc trên một mẫu trang thuật ngữ phân loại tùy chỉnh nơi chúng tôi muốn các mục được kết nối với thuật ngữ được sắp xếp theo ngày xuất bản (trường ngày tùy chỉnh) - và nếu có nhiều mục trong cùng một ngày (được định dạng như YYYY-MM- DD) để sắp xếp chúng theo tiêu đề và cuối cùng sắp xếp theo tiêu đề nếu trường tùy chỉnh chưa được điền (các mục cũ hơn).

Vì vậy, tôi đã thử hàng trăm cách khác nhau với WP_query và nó trả về hầu hết các kết quả như tôi muốn - nhưng trong trường hợp này, nó chỉ trả về các mục có meta_key của Publishing_date. Tất cả các mục khác đang bị bỏ qua và không được hiển thị. Tôi đã thử một meta_query bằng cách sử dụng mối quan hệ "hoặc" và so sánh ấn phẩm_date là EXISTS và KHÔNG EXISTS, nhưng điều đó trả về 0 kết quả cho tôi.

Ngoài ra, trang web vẫn đang chạy 3.5.2 và họ không muốn nâng cấp.

Đây là truy vấn gần đây nhất của tôi giúp tôi có các bài đăng có trường tùy chỉnh ấn phẩm_date được hiển thị theo đúng thứ tự:

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

Tôi cũng đã thử sử dụng wpdb và chạy truy vấn SQL, nhưng tôi thực sự không chắc chắn làm thế nào để thực hiện những gì tôi muốn làm điều đó. Nếu ai đó có thể giúp tôi ra thì đó sẽ là tuyệt vời!

Cảm ơn trước.


Ngạc nhiên là cách tiếp cận meta_query không hoạt động, nhưng một lần nữa, bạn không thể đặt hàng giá trị meta với meta_query mà không có bộ meta_key.
sanchothefat

Tôi nghĩ đó là vấn đề tôi đang gặp phải. Cuối cùng tôi đã có một truy vấn meta hoạt động: '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' ) ),nhưng thứ tự không hoạt động: \
CSSgirl 17/12/13

vâng, việc đặt hàng phụ thuộc vào meta_key không may được đặt bên ngoài tax_query. Câu trả lời của tôi dưới đây có thể giúp đỡ.
sanchothefat

Câu trả lời:


19

Cám ơn sự giúp đỡ từ mọi người!

Cuối cùng, truy vấn bên dưới đã cho tôi kết quả mà tôi mong muốn - đó là hiển thị và sắp xếp các bài đăng theo trường tùy chỉnh "Publishing_date" - sắp xếp theo ngày và nếu có nhiều ngày trong cùng một ngày (giả sử, 4 đánh dấu Tháng 6 năm 2013), nó sẽ sắp xếp những người theo tiêu đề. Sau đó, sau khi nó chạy qua tất cả các bài đăng có Ngày xuất bản được điền vào, nó sẽ lặp lại các bài đăng còn lại, theo thứ tự bảng chữ cái.

Điều này mang lại cho tôi các kết quả được đặt trong cùng một truy vấn và giữ nguyên phân trang của tôi:

$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
Tốt đẹp. Tôi không bao giờ nghĩ để chạy hai meta_querytrên cùng một khóa!
GhostToast

5
Đối với tôi (sử dụng WordPress 4.1.1), nếu tôi đặt meta_keytự động, nó sẽ không bao gồm nó ngay cả với NOT EXISTS. Tôi thực sự hy vọng tôi đang làm gì đó sai.
Ryan Taylor

1
@RyanTaylor tương tự ở đây - meta_key không được đặt trong truy vấn để làm việc này, nhưng nó dường như sắp xếp chính xác theo giá trị meta ngay cả khi khóa meta không được đặt.
jammypeach

2
Như các bình luận ở trên, cho WP 4.1+ loại bỏ hoặc bình luận 'meta_key' => 'publication_date',.
MikeiLL

7

Vài năm sau, mã được đăng bởi CSSGirl không hoạt động với tôi vì có một số bài đăng không có khóa meta hoặc khóa meta trống nên đây là điều tôi phải làm để có tất cả các bài đăng theo ngày và hiển thị những cái có hiển thị giá trị khóa meta trước:

$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

Tôi nghĩ rằng bạn cần phải làm 2 vòng riêng biệt. Bạn có thể nắm bắt tất cả các bài viết được tìm thấy trong vòng lặp đầu tiên và loại trừ chúng khỏi vòng lặp thứ cấp đủ dễ dàng:

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

Sau đó chạy vòng lặp thứ hai của bạn.


Cố gắng bây giờ, cảm ơn. Sẽ cho bạn biết nếu nó hoạt động!
CSSgirl 17/12/13

1
Điều này đã làm việc - nhưng nó đã phá vỡ phân trang - bất kỳ ý tưởng làm thế nào để làm cho nó hoạt động? Đây là những gì nó trông giống như bây giờ: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 17/12/13

Hừm. Không phải là tôi có thể nghĩ ra.
GhostToast 17/12/13

1

Có bất kỳ lý do nào bạn không thể thực thi khóa meta Publishing_date để tồn tại cho mỗi bài đăng chỉ với một giá trị trống không?

Vì vậy, trong save_posthành động của bạn, bạn sẽ thêm / cập nhật khóa meta cho dù $_POSTgiá trị có trống hay không.

Bạn sẽ phải chạy một kịch bản cập nhật để lặp lại các bài đăng cũ hơn và thêm khóa với giá trị trống, ví dụ:

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

Chạy nó bằng cách duyệt đến http://example.com/wp-admin/?update_old_posts

Sau đó, bạn có thể sử dụng cùng một truy vấn như bạn có. Bạn có thể muốn thêm một bộ lọc bổ sung để cho phép bạn sắp xếp theo các cột khác nhau theo các hướng khác nhau, điều đó có ý nghĩa với tôi để sắp xếp theo ngày theo thứ tự giảm dần và tiêu đề theo thứ tự tăng dần.

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, tôi đã không nghĩ về điều đó. Tôi sẽ thử nó và xem nó diễn ra như thế nào, cảm ơn!
CSSgirl

0

Tôi đã tạo một mệnh đề tùy chỉnh. Tôi đã thử nghiệm nó bằng cách sử dụng $wp_query->requestngay trước vòng lặp chính của mình, tôi thực sự không biết rõ về SQL, nhưng điều này dường như giúp mọi thứ hoạt động.

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

Ngoài ra, bạn có thể thiết lập compaređể 'EXISTS'và thay đổi dòng trong add_trending_where tới $where .= " OR ($wpdb->postmeta.post_id IS NULL)";. Sau đó, bạn chỉ phải thay đổi giá trị của khóa ở một nơi. Một lần nữa, lặp lại $wp_query->requestvà chơi xung quanh nếu bạn muốn hiểu điều này tốt hơn hoặc điều chỉnh nó.

EDIT: Tôi chỉ nhận thấy điều này không hoạt động nếu meta_keyđược đặt trên truy vấn. Bạn có thể sử dụng $query->set('meta_key', NULL);nếu bạn phải.

EDIT 2: Tôi đã làm việc này với phương pháp trên. Vì một số lý do, ban đầu nó không hoạt động (có thể meta_key đã được đặt ... Tôi không biết).

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'));
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.