0

I'm trying to create an advanced, reusable query function.

I need to query by category OR a category + a tag.

I know how to do this with custom fields (meta queries) but how do I do it with simple categories and tags?

A pseudo SQL Query would be:

Select * from Posts where ( cat_id = 1 OR (cat_id = 5 AND tag_id = 6) )

The query could change to need to include a set of tags

Select * from Posts where ( cat_id = 1 OR ( cat_id = 5 AND tag_id = (5,6,7) ))

Currently I'm using wp_query and passing args, but I guess I could write a one-off query_posts if needed.

Here is a rough version of my custom query. I'm guessing I need to add another argument for my desired 'or' statement?

$args = array(
     'post_type'            => $postType, //assume 'post'
     'cat'                  => $cat_id, //currently a single id
     'orderby'              => 'date',
     'post_status'          => 'publish',
    );

I got some help from Best practice for multiple queries on page

So now I need to add a tax_query, but here is where my query fails

$taxQuery = array(
       'relation' => 'AND',  //Is this "And" my original query, or just "and" these two parameters?            
                array(
                    'taxonomy' => 'category',
                    'field' => 'id',
                    'terms' => 5
                ),
                array(
                    'taxonomy' => 'post_tag',
                    'field' => 'id',
                    'terms' => array(5,6,7)
                )
        );

My updated WP_query would be :

$args = array(
     'post_type'            => $postType, //assume 'post'
     'cat'                  => $cat_id, //currently a single id
     'tax_query'            => $taxQuery,
     'orderby'              => 'date',
     'post_status'          => 'publish',
    );

Thank you for your time!

  • and/or what? --------- – user6686780 Feb 11 '17 at 22:33
2

I am not 100% sure what you are asking but as written that is going to be wrong. tax_query is an array of arrays but you have an array of array of arrays. You create the third array when you put $taxQuery into array($taxQuery). This should be more correct:

$args = array(
     'post_type'            => $postType, //assume 'post'
     'cat'                  => $cat_id, //currently a single id
     'tax_query'            => $taxQuery,
     'orderby'              => 'date',
     'post_status'          => 'publish',
);

With your version, if you var_dump the query you can see 0=1 in the SQL which reflects the broken tax_query, and if you have debugging enabled you can see Notices.

Unfortunately, you can't do a complicated query like this one...

Select * from Posts where ( cat_id = 1 OR ( cat_id = 5 AND tag_id = (5,6,7) ))

... with WP_Query. The nested conditions in the WHERE are too complex for WP_Query.

You have several options:

  1. Write the SQL yourself
  2. Let WP_Query do part of the work and alter, at the very least, the WHERE clause with posts_where
  3. Run several queries to grab the data.

The latter would look something like:

$post_ids = new WP_Query(array(
  // query for one post type
  'fields' => 'ids',
  // other parameters
));

$post_ids_2 = new WP_Query(array(
  // query for the others
  'fields' => 'ids',
  // other parameters
));
// join them
$post_ids = $post_ids->posts + $post_ids_2->posts;
$posts_qry = new WP_Query(array('post__in'=> $posts_ids));

That is taken from another answer so none of the parameter are right for you but that should give you idea. That is by far the easiest solution but also the least efficient.

  • Thanks - you are correct - I had another function that was taking an array of arrays for an advanced date filter. Still, this doesn't answer the question. – Nate Jul 3 '13 at 17:48
  • @Nate : see the edit – s_ha_dum Jul 3 '13 at 18:15
1

One way to do the AND / OR nested query, which worked for me, is to simply pass an array of values. I believe it implicitly uses the list as an OR via the IN(a,b...) MySQL syntax.

Here's an example that I was able to use for a taxonomy query:

// ... Other query params in $query

$query['tax_query'] = ['relation' => 'AND'];

$query['tax_query'][] =[[   'taxonomy' => 'field_a',
                            'field' => 'slug',
                            'terms' => ['a','b','c']]; // this is the "OR"


$query['tax_query'][] =[[   'taxonomy' => 'field_b',
                            'field' => 'slug',
                            'terms' => ['d','e','f']]; // this is the "OR"


$get_posts = new WP_Query;
$posts = $get_posts->query($query);

This in essence generates a query such as:

field_a IN('a','b','c') AND field_b IN('d','e','f')

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.