リストをメタキー(存在する場合)で最初にソートし、メタキーのない残りの投稿をタイトル順に並べるクエリ


22

私はカスタム分類用語ページテンプレートで作業していますDD)次にそれらをタイトルで並べ替え、カスタムフィールドが入力されていない場合はタイトルで並べ替えます(古いアイテム)。

したがって、WP_queryを使用して100種類の方法を試してみましたが、ほとんどの結果が必要に応じて返されますが、この場合は、public_dateのmeta_keyを持つアイテムのみが返されます。他のすべてのアイテムは無視され、表示されません。「or」のリレーションを使用してmeta_queryを試し、publication_dateをEXISTSおよびNOT EXISTSとして比較しましたが、0の結果が返されました。

また、サイトはまだ3.5.2を実行しているため、アップグレードする必要はありません。

以下は、public_dateカスタムフィールドが正しい順序で表示されている投稿を取得する最新のクエリです。

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

また、wpdbを使用してSQLクエリを実行しようとしましたが、それを実行する方法を実際にどのように実現するかはわかりません。誰かが私を助けることができれば、それは素晴らしいでしょう!

前もって感謝します。


驚いたことに、meta_queryアプローチは機能しませんでしたが、meta_keyを設定せずにmeta_queryでメタ値を並べ替えることはできません。
サンチョテファ

それが私が抱えている問題だと思います。最終的に'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はtax_queryの外部に設定されていることに依存しています。しかし、以下の私の答えが役立つかもしれません。
サンチョテファ

回答:


19

皆さん、助けてくれてありがとう!

最後に、以下のクエリは私が望む結果を得ました-最初に「publication_date」のカスタムフィールドで投稿を表示およびソートすることでした-日付でソートし、同じ日付が複数ある場合(たとえば、4 2013年6月)、タイトルで並べ替えます。その後、出版日が記入されたすべての投稿を実行した後、タイトルのアルファベット順に残りの投稿をループします。

これにより、同じクエリで結果セットが取得され、ページネーションが保持されます。

$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
いいね meta_query同じキーで2つ実行することは考えていませんでした!
GhostToast

5
私(WordPress 4.1.1を使用)の場合、meta_key自動的に設定した場合、でさえも含まれませんNOT EXISTS。何か間違ったことをしていることを本当に願っています
ライアンテイラー

1
ここでも@RyanTaylorと同じ-これが機能するためには、クエリでmeta_keyを設定しないでください。ただし、メタキーが設定されていなくても、メタ値によって正しく順序付けされているようです。
ジャミーピーチ

2
上記のコメントのように、WP 4.1+の場合、削除またはコメントアウトし'meta_key' => 'publication_date',ます。
MikeiLL

7

数年後、CSSGirlによって投稿されたコードは、メタキーを持たない投稿やメタキーが空だった投稿があったため、私にとっては機能しませんでした。そして、最初にメタキー値を表示するものを表示します。

$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つの別々のループを行う必要があると思います。最初のループで見つかったすべての投稿をキャプチャし、二次ループから簡単に除外できます:

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

次に、2番目のループを実行します。


今、これを試して、ありがとう。動作するかどうかをお知らせします!
CSSgirl

1
これは機能しましたが、ページネーションを壊しました-これを機能させる方法はありますか?ここではそれが今のようになります: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

うーん 私が考えることはできません。
GhostToast

1

すべての投稿に値が空であるだけでpublication_dateメタキーを強制できなかった理由はありますか?

したがって、save_postアクションで$_POSTは、値が空かどうかに関係なく、メタキーを追加/更新します。

更新スクリプトを実行して古い投稿をループし、空の値を持つキーを追加する必要があります。例:

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を参照して実行します

その後、同じクエリを使用できます。別のフィルターを追加して、異なる方向の異なる列で並べ替えることができます。日付の降順とタイトルの昇順で並べ替えることは意味があります。

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

うーん、私はそれを考えていませんでした。試してみて、どうなるか見てみましょう、ありがとう!
CSSgirl

0

カスタムwhere句を作成しました。$wp_query->requestメインループの直前に使用してテストしましたが、SQLについてはあまりよくわかりませんが、これでうまくいくようです。

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

または、add_trending_whereの行をに設定compare'EXISTS'て変更することもできます$where .= " OR ($wpdb->postmeta.post_id IS NULL)";。その後、1つの場所でキーの値を変更するだけで済みます。繰り返しますが、$wp_query->requestこれをよく理解したい場合や微調整したい場合は、エコーして再生してください。

編集:meta_keyクエリにが設定されている場合、これが機能しないことに気付きました。必要に$query->set('meta_key', NULL);応じて使用できます。

編集2:私はこれを上記の方法で動作させました。何らかの理由で、最初は設定されていませんでした(おそらくmeta_keyが設定されていました...わかりません)。

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'));
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.