Skip Navigation

[Resolved] Set Custom Search to AND instead of OR

This thread is resolved. Here is a description of the problem and solution.

Problem:
Views taxonomy filters apply an OR condition on posts instead of an AND. The user would like to get the posts that are assigned to all the selected terms.

Solution:
This requires custom code. Check the example here https://toolset.com/forums/topic/set-custom-search-to-and-instead-of-or/#post-2155235

This support ticket is created 3 years, 2 months ago. There's a good chance that you are reading advice that it now obsolete.

This is the technical support forum for Toolset - a suite of plugins for developing WordPress sites without writing PHP.

Everyone can read this forum, but only Toolset clients can post in it. Toolset support works 6 days per week, 19 hours per day.

Sun Mon Tue Wed Thu Fri Sat
9:00 – 13:00 9:00 – 13:00 9:00 – 13:00 9:00 – 13:00 - - 9:00 – 13:00
14:00 – 18:00 14:00 – 18:00 14:00 – 18:00 14:00 – 18:00 - - 14:00 – 18:00

Supporter timezone: Africa/Casablanca (GMT+01:00)

This topic contains 4 replies, has 2 voices.

Last updated by scottL-3 3 years, 1 month ago.

Assisted by: Jamal.

Author
Posts
#2153955
Screen Shot 2021-08-27 at 4.33.32 PM.png

Tell us what you are trying to do?

I am building a recipes site with the recipes in the standard Posts post type with some custom fields. The Posts are related to a CPT for Ingredients with intermediary fields for quantity, unit of measure and preparation notes such as "1", "tablespoon" and "minced". Standard categories are used for things like "Breakfast", "Dinner", "Mexican", "Vegetarian", etc.

In the blog archive I have a custom search with these filters added:
Category as a select field
Ingredient relationship as a multi-select field
Text search

I want the search to only show results that match all of those search fields but it is showing results that match any of those search fields. In other words, I want an "AND" search but it is giving me an "OR" search.

I cannot see a place to specify AND instead of OR. Normally I'd do this in the Query Filter section of the Archive's settings but it isn't offering that option when I add the search filters through the custom search section of the page.

Attached screenshot shows the Query Filter settings. Note there is not place to set AND or OR.

Is there any documentation that you are following?

Not really. I've done a lot of custom searches and a lot of query filters and I am familiar with the documentation for both but I don't think this need is covered in either.

Is there a similar example that we can see?

This site is on my localhost but I can package it up with duplicator if needed. The site is so simple right now that it might be just as fast for you to setup a test site, create a CPT, relate it to the standard Post with at least one intermediary field, create a few posts, categorize them, and relate them to at least one CPT. Then build a View with custom search filters for Category and the related CPT type and a text search.

NOTE: I also looked at a View on another site where I think I used to be able to set AND or OR and I don't see the settings there now either. Might something have taken these away in a recent update?

What is the link to your site?

It is on localhost so not accessible from the internet at this time.

#2154227

Hello and thank you for contacting Toolset Support.

The search uses AND for criteria of different kinds and allows to use of AND or OR in criteria of the same kind. For example, you can have AND or OR in nested queries for the custom fields, or taxonomies. But different kinds will always use AND.

So, I am guessing that something odd is there and I'll need to further debug it to understand it. I'll need the following:
- A duplicator package of your website.
- A test scenario that I can follow to see the issue. (search criteria to choose and the expected result, and the unexpected results).

I am setting your next reply to be private to let you share a download link safely. Please share an administrator account too.

#2155235

Thank you for the credentials, I understand the issue better now. You want to have an AND operator in the relationship filter. That's not possible out of the box. The relationship filter only uses an OR operator.

However, we do have our own API for the WP_Query to achieve this. Read more about it here https://toolset.com/documentation/customizing-sites-using-php/post-relationships-api/how-to-migrate-your-site-to-new-post-relationships/

However, I was not able to make it work with the following custom code:

function my_is_blog_archive_loop( $query ){
  $is_fake = $query->get('wpv_fake_archive_loop');
 
  if ( is_array( $is_fake ) ) {
    $archive_type = $is_fake['name'];       
  } else {
    $archive_type = '';     
  }

  if ( $archive_type == 'home' || is_post_type_archive( 'post' ) && !is_admin() ) {
    return true;
  }
  return false;
}

function my_get_related_posts( $query ){
  $posts = array();
  if ( isset($_POST['action']) ){
    if( isset($_POST['search']) && isset($_POST['search']['dps_general'])){
      foreach($_POST['search']['dps_general'] as $param){
        if($param['name'] == 'wpv-relationship-filter[]')
          $posts[] = (int) $param['value'];
      }
    }
  } else {
    error_log('$_GET: ' . print_r( $_GET, true ) );
    $posts = $_GET['wpv-relationship-filter'];
  }
  return $posts;
}

add_filter( 'pre_get_posts', 'my_callback_function', 9999, 1 );
function my_callback_function( $query ){
  if ( my_is_blog_archive_loop( $query ) ) {
    $related = my_get_related_posts( $query );
    if ( count($related)<2) return;
    
    $rules = array();
    foreach($related as $post){
      $rules[] = array(
        'role' => 'parent',
        'related_to' => $post,
        'relationship' => 'post-ingredient'
      );
    }
    
    $query = new WP_Query( 
      array(
        'post_type' => 'post',
        'fields' => 'ids',
        'posts_per_page' => -1,
        'toolset_relationships' => $rules,
      )
    );
    $posts = $query->posts;
    if( count($posts) > 0 ){
      error_log('we got something ' . print_r( $posts, true ) );
      // $query->query_vars['post__in'] = $posts;
      $query->set('post__in', $post);
    }else{
      error_log('we got nothing ' . print_r( $posts, true ) );
      // $query->query_vars['post__in'] = array(0);
      $query->set('post__in', array(0));
    }
  }
}

Let me approach our 2nd tier for assistance on this and get back to you as soon as possible.

#2186145

My apologies for the late reply, I am afraid, I missed our 2nd Tier response, most probably because of a weekend or a vacation.

It turns out that the issue is with priority. I tried with 9999 and our 2nd Tier fixed the issue using 10001. Please check again from your side and let us know if that helps.

#2188355

I'd prefer a solution that doesn't need code but appreciate the code sample since that is the only way right now.