2017-08-28 72 views
8

背景複雜custom_field搜索與meta_query

我公司採用先進的自定義字段臨來管理我的自定義字段和他們有一個包含存儲爲repeatername_X_fieldname子場一個「轉發」字段,其中X是行數的中繼器。

我有一個自定義後類型student具有中繼attendance包含dateclass

所以,當學生參加一類,它將存儲他們的出席如下

  • meta_key: 'attendance_X_date' meta_value: '20170701'
  • meta_key: 'attendance_X_class' meta_value:'歷史101'

In或DER尋找誰一直到某一類或某一日期範圍內參加任何學生,我要鉤住get_meta_sql和轉換我meta_query使用LIKE而不是=值包含%

function key_rewrite($parts){ 
    foreach($parts as &$part){ 
     $part = preg_replace("/(meta_key =)(\'[^']*[%][^']*\')/", "meta_key LIKE $2", $part); 
    } 
    return $parts; 
} 
add_action('get_meta_sql', 'key_rewrite'); 

這讓我做這樣的事情

$args = array(
    'post_type' => 'student', 
    'meta_query' => array(
     array(
      'key'=>'attendance_%_class', 
      'compare'=>'=', 
      'value'=>'History 101' 
     ) 
    ) 
); 
$my_query = new WP_Query($args); 

爲了尋找人誰參加歷史101或

$args = array(
    'post_type' => 'student', 
    'meta_query' => array(
     array(
      'key'=>'attendance_%_date', 
      'compare'=>'>=', 
      'value'=>'20170101' 
     ) 
    ) 
); 

尋找今年參加的人。

問題部分1

我需要能夠搜索到的人誰也參加了今年的「歷史101」。

起初,這似乎是一個簡單並在meta_query會做的伎倆:

$args = array(
    'post_type' => 'student', 
    'meta_query' => array(
     'relation' => 'AND', 
     array(
      'key'=>'attendance_%_class', 
      'compare'=>'=', 
      'value'=>'History 101' 
     ), 
     array(
      'key'=>'attendance_%_date', 
      'compare'=>'>=', 
      'value'=>'20170101' 
     ) 
    ) 
); 

然而,因爲通配符沒有聯繫,這樣做可能會返回一個人誰出席「歷史101」去年,但今年的課程不同。

問題部分2

實際上需要能夠得到誰出席「歷史101」這一年,但並沒有表現出向上的類都在過去一週我們每個人的列表。這進一步使問題更加複雜,因爲我需要將meta_query的EXISTSNOT EXISTS與其他條件結合起來。再次,從表面上看,這聽起來相當簡單使用嵌套meta_queries:

$args = array(
    'post_type' => 'student', 
    'meta_query' => array(
     'relation' => 'AND', 
     array(
      'relation' => 'AND', 
      array(
       //Just assume by some magic we resolved Problem part 1 
       'key'=>'attendance_%_class', 
       'compare'=>'=', 
       'value'=>'History 101' 
      ), 
      array(
       'key'=>'attendance_%_date', 
       'compare'=>'>=', 
       'value'=>'20170101' 
      ) 
     ), 
     array(
      'relation' => 'AND', 
      array(
       //again... magic! 
       'key'=>'attendance_%_class', 
       'compare'=>'=', 
       'value'=>'History 101' 
      ), 
      array(
       'key'=>'attendance_%_date', 
       'compare'=>'>', 
       'value'=>'20170821' 
      ), 
      array(
       'key'=>'attendance_%_date', 
       'compare'=>'NOT EXISTS' 
      ) 
     ) 
    ) 
); 

顯然,這是造成與邏輯問題,但令人印象深刻的WordPress由postmeta表中一次每次使用在元查詢加盟解決了大部分。不幸的是,這意味着>日期部分不在NOT EXISTSON中使用,因此不能使用IS NULL來測試它不存在。

我知道這非常複雜,如果你跟着我,我印象深刻。如果沒有,請提出問題,以便我澄清。

是的,我知道我可以完全寫我自己的查詢,但我試圖堅持內置的WordPress工具。

幫助!

回答

3

我一直在那裏...試圖把所有的一個複雜的元查詢。最後,您需要手動處理生成的SQL - 移動括號,替換運算符,引號等。

最後,查詢非常複雜,並且與postmeta表有多個JOINS,因此它變得太貴且太慢。

我選擇了通過選擇稍微不同的方法來實現這一目標。 所以,你所能做的就是劃分查詢到幾個子查詢和後來與post__inpost__not_in將它們結合起來,

例如用於問題第1部分

/* Filter by class */ 
$history_students_ids = get_posts(array(
    'post_type'  => 'student', 
    'fields'   => 'ids', 
    'posts_per_page' => -1, 
    'meta_query'  => array(
     array(
      'key'=>'attendance_%_class', 
      'compare'=>'=', 
      'value'=>'History 101' 
     ), 
    ) 
)); 

/* Filter by date */ 
$students = get_posts(array(
    'post_type' => 'student', 
    'post__in' => $history_students_ids, 
    'meta_query' => array(
     array(
      'key'=>'attendance_%_date', 
      'compare'=>'>=', 
      'value'=>'20170101' 
     ) 
    ) 
)); 

這同樣適用於問題部分2

$not_attended_history_students_ids = get_posts(array(
    'post_type' => 'student', 
    'post__in' => $history_students_ids, 
    'fields'   => 'ids', 
    'posts_per_page' => -1, 
    'meta_query' => array(
     array(
      'key'=>'attendance_%_date', 
      'compare'=>'NOT EXISTS' 
     ) 
    ) 
)); 

$students = get_posts(array(
    'post_type' => 'student', 
    'post__in' => $not_attended_history_students_ids, 
    'meta_query' => array(
     array(
      'key'=>'attendance_%_date', 
      'compare'=>'>=', 
      'value'=>'20170101' 
     ) 
    ) 
)); 

可以逆轉出勤條件是EXISTS和使用post__not_in ...我希望你能理解這個想法。

+0

乍一看,這似乎是一個很好的解決方案。只要我有機會,我會測試它,讓你知道。 – trex005

+0

好的。這對第2部分非常有用。但第1部分仍然存在相同的問題。例如,如果「學生1」去年參加了「歷史101」,他將會出現在第一個「get_posts」結果中。那麼,如果他今年參加了「歷史102」,他將會在第二個'get_posts'中。 – trex005

+0

在第二個循環中嘗試Wp_query post__not_in(https://codex.wordpress.org/Class_Reference/WP_Query) – GNANA