Support » Fixing WordPress » meta_query compare NOT IN with an array of post meta

  • Resolved metaphorcreations

    (@metaphorcreations)


    I have a custom meta field called “_tops_ticket_read”. This field gets added to by using “add_post_meta” and “delete_post_meta”, so when using “get_post_meta”, with the single boolean set to false, it returns an array of data. Examples:

    add_post_meta( $this->get_post_id(), '_tops_ticket_read', get_current_user_id() );
    delete_post_meta( $this->get_post_id(), '_tops_ticket_read', get_current_user_id() );
    $read_array = get_post_meta( $this->get_post_id(), '_tops_ticket_read' );

    Now, I’m attempting to use this data to filter a get_posts query by adding it to a meta_query. It works as expected when I use the following query (using compare=>’IN’:

    $args = array(
      'posts_per_page' => -1,
      'order' => 'ASC',
      'post_type' => 'my_custom_post_type',
      'meta_query' => array(
        'is_read' => array(
          'key' => '_tops_ticket_read',
          'value' => get_current_user_id(),
          'compare' => 'IN'
        )
      )
    );
    
    $posts = get_posts( $args );

    This returns all the posts where the current user’s ID is contained in the array of metadata for “_tops_ticket_read”.

    But, if I try to query the posts where the user’s ID is not contained in the metadata:

    $args = array(
      'posts_per_page' => -1,
      'order' => 'ASC',
      'post_type' => 'my_custom_post_type',
      'meta_query' => array(
        'is_read' => array(
          'key' => '_tops_ticket_read',
          'value' => get_current_user_id(),
          'compare' => 'NOT IN'
        )
      )
    );
    
    $posts = get_posts( $args );

    It returns all the posts instead of just the posts that I would like to get.

    Does anyone have experience in dealing with this?

    Thanks!

Viewing 5 replies - 1 through 5 (of 5 total)
  • Hey metaphorcreations,

    I can’t imagine this being a bug straight off the bat.

    Otto does a good job of explaining what you might be facing over at
    https://wordpress.stackexchange.com/questions/66056/filter-posts-with-meta-query-not-in-where-value-has-multiple-values

    In short, I’d probably check that you don’t have multiple meta rows, change your value parameter to an array and check posts contain the meta field with a value.

    Hope this helps.

    Thread Starter metaphorcreations

    (@metaphorcreations)

    Ok, I think what I’m trying to accomplish is different than what the NOT IN comparative is meant to do. The meta field I’m querying does have multiple rows.

    I’m trying to query posts by the “_tops_ticket_read” meta field, which has multiple rows (when using get_post_meta( $this->get_post_id(), ‘_tops_ticket_read’ ); it returns an array). And return all posts that do not contain a specific value (the current user’s ID) within any of the rows for that meta.

    So, it sounds like the NOT IN comparative only works if the meta value is a singular value and the “value” field of the meta_query is an array()… But, I want it to work the other way. Where the “value” field is a single value, and the meta field being queried has multiple rows/values.

    For some reason the opposite comparative “IN” works just fine this way… But, I’m guessing the query pulls all the rows for the meta and compares that against the “value”, as opposed to the other way around.

    As of right now I have found a solution, but it entails making two separate queries. The first query returns all the posts that match my “IN” meta_query. The second query returns all posts regardless of meta value. Then I have to use the “array_udiff()” function to find the difference between the 2 sets of queries, which then gives me the posts I’m shooting for (all the posts that do not contains any meta rows for “_tops_ticket_read” with the current user’s ID).

    So, I basically have (this is a bit simplified version of my final queries which are larger):

    $args = array(
      'posts_per_page' => -1,
      'post_type' => 'tops_ticket',
      'meta_query' => array(
        'is_read' => array(
          'key' => '_tops_ticket_read',
          'value' => get_current_user_id(),
          'compare' => 'IN'
        )
      )
    );
    $read_tickets = get_posts( $args );
    
    $args = array(
      'posts_per_page' => -1,
      'post_type' => 'tops_ticket',
      )
    );
    $all_tickets = get_posts( $args );
    
    $unread_tickets = array_udiff( $all_tickets, $read_tickets, 'tops_remove_duplicate_posts' );

    And the following function finds the difference between the 2 queries

    function tops_remove_duplicate_posts( $post_a, $post_b ) {
      return $post_a->ID - $post_b->ID;
    }

    … So, this works. But, it would be nice to get the same results using a single query. Is this possible? It seems like it would be a part of the meta_query family of options.

    Thread Starter metaphorcreations

    (@metaphorcreations)

    @adam3128, not sure if you’re subscribed to this post so I’m just tagging you quickly so you see it.

    Thanks for the feedback!

    Hey metaphorcreations,

    Hope you’re having a good weekend.

    Is the value in the database a serialized array? If you want to use a single value to search a meta field which is a serialized array maybe trying giving the compare the LIKE and NOT LIKE parameter.

    https://wordpress.stackexchange.com/questions/70864/meta-query-compare-operator-explanation gives a really good answer to what all the comparisons do.

    https://wordpress.stackexchange.com/questions/55354/how-can-i-create-a-meta-query-with-an-array-as-meta-field – The first two answers here go over what you might be after. The second answer in particular is regarding user ID’s as well.

    Hope this helps

    Thread Starter metaphorcreations

    (@metaphorcreations)

    Thanks for the response. Unfortunately, I still wasn’t able to accomplish what I needed. I’ll just stick with my solution mentioned above https://wordpress.org/support/topic/meta_query-compare-not-in-with-an-array-of-post-meta/#post-9189116

    Thanks!

Viewing 5 replies - 1 through 5 (of 5 total)
  • The topic ‘meta_query compare NOT IN with an array of post meta’ is closed to new replies.