首页 > 解决方案 > 混合 OR AND 分类查询

问题描述

我已经创建了一个 WP Query 参数列表,就像这样希望它会选择所有带有术语 2 的帖子,然后从结果中选择所有其他具有 OR 关系的帖子。

$similar_properties_args = array(
    'post_type' => 'property',
    'posts_per_page' => '10',
    'post__not_in' => array(get_post_ID() ),
    'post_parent__not_in' => array(get_post_ID() ),   
    
    'tax_query' => array(
        'relation' => 'AND',
        array(
            'taxonomy' => 'language',
            'terms' => '2'
        ),
        array (
        'relation' => 'OR',
            array(
                 array(
                    'taxonomy' => 'property-feature',
                    'field' => 'id',
                    'terms' => array(1954,1958,1966,1970,1972)
                ),
                array(
                    'taxonomy' => 'property-city',
                    'field' => 'id',
                    'terms' => array(145)
                ),
                array(
                    'taxonomy' => 'property-status',
                    'field' => 'id',
                    'terms' => array(38)
                ),
                array(
                    'taxonomy' => 'property-type',
                    'field' => 'id',
                    'terms' => array(21)
                    )
                
                )
            )       
    )
);

创建的实际 WP mysql 查询如下:

SELECT SQL_CALC_FOUND_ROWS  agn_posts.ID FROM agn_posts  LEFT JOIN agn_term_relationships ON (agn_posts.ID = agn_term_relationships.object_id)  LEFT JOIN agn_term_relationships AS tt1 ON (agn_posts.ID = tt1.object_id)  LEFT JOIN agn_term_relationships AS tt2 ON (agn_posts.ID = tt2.object_id)  LEFT JOIN agn_term_relationships AS tt3 ON (agn_posts.ID = tt3.object_id)  LEFT JOIN agn_term_relationships AS tt4 ON (agn_posts.ID = tt4.object_id) WHERE 1=1  AND agn_posts.ID NOT IN (1440) AND agn_posts.post_parent NOT IN (1440) AND ( 
  agn_term_relationships.term_taxonomy_id IN (2) 
  AND 
  ( 
    ( 
      tt1.term_taxonomy_id IN (1954,1958,1966,1970,1972) 
      AND 
      tt2.term_taxonomy_id IN (145) 
      AND 
      tt3.term_taxonomy_id IN (38) 
      AND 
      tt4.term_taxonomy_id IN (21)
    )
  )
) AND agn_posts.post_type = 'property' AND (agn_posts.post_status = 'publish' OR agn_posts.post_status = 'private') GROUP BY agn_posts.ID ORDER BY agn_posts.post_date DESC LIMIT 0, 10

...它并没有给我我需要得到的结果。

如果我将 tt1 术语关系更改为 OR,那么结果很好。

 tt1.term_taxonomy_id IN (1954,1958,1966,1970,1972) 
          OR  //from AND to OR
          tt2.term_taxonomy_id IN (145) 
          OR //from AND to OR
          tt3.term_taxonomy_id IN (38) 
          OR //from AND to OR
          tt4.term_taxonomy_id IN (21)

问题是,从我的肉眼来看,上面的参数列表对于创建我正在寻找的查询是有效的,但不知何故缺少了一些东西。您可能会看到,我的代码中的问题在哪里?

标签: wordpress

解决方案


您不应该将四个数组/子句嵌套在一个数组中:

'tax_query' => array(
    'relation' => 'AND', // for clauses 1 and 2
    array( // clause 1
        'taxonomy' => 'language',
        'terms'    => '2',
    ),
    array( // clause 2
        'relation' => 'OR', // for sub-clause 1..

        // you shouldn't nest the sub-sub-clauses
        array( // sub-clause 1
            array( // sub-sub-clause 1
                'taxonomy' => 'property-feature',
                ...
            ),
            array( // sub-sub-clause 2
                'taxonomy' => 'property-city',
                ...
            ),
            array( // sub-sub-clause 3
                'taxonomy' => 'property-status',
                ...
            ),
            array( // sub-sub-clause 4
                'taxonomy' => 'property-type',
                ...
            ),
        ),
    ),
),

相反,使数组与以下级别相同relation

'tax_query' => array(
    'relation' => 'AND', // for clauses 1 and 2
    array( // clause 1
        'taxonomy' => 'language',
        'terms'    => '2',
    ),
    array( // clause 2
        'relation' => 'OR', // for the sub-clauses 1, 2, 3 and 4

        // instead of nesting, do like so:
        array( // sub-clause 1
            'taxonomy' => 'property-feature',
            'terms'    => array( 1954, 1958, 1966, 1970, 1972 ),
        ),
        array( // sub-clause 2
            'taxonomy' => 'property-city',
            'terms'    => array( 145 ),
        ),
        array( // sub-clause 3
            'taxonomy' => 'property-status',
            'terms'    => array( 38 ),
        ),
        array( // sub-clause 4
            'taxonomy' => 'property-type',
            'terms'    => array( 21 ),
        ),
    ),
),

并且那个会给你这个 SQL 命令作为以下内容的一部分WHERE

agn_term_relationships.term_taxonomy_id IN (2) # language
  AND 
  ( 
    tt1.term_taxonomy_id IN (1954,1958,1966,1970,1972) # feature
    OR 
    tt1.term_taxonomy_id IN (145) # city
    OR 
    tt1.term_taxonomy_id IN (38)  # status
    OR 
    tt1.term_taxonomy_id IN (21)  # type
  )

顺便说一句,'field' => 'id'应该是'field' => 'term_id',但默认字段确实是term_id,所以你可以省略fieldarg。此外,WordPress 没有名为 的函数get_post_ID,所以我认为您的意思是使用get_the_ID()? :)


推荐阅读