0

I'm trying to perform a scheduled update to all posts, 10 posts at time.

To achieve this, I run Cron job with a script that saves 2 post meta:

  • $DATA: the data I want to be update
  • $TIME: the UNIX timestamp: time(), to know when that post has been updated with a new $DATA

As I have a lot of posts that do not have the $DATA postmeta, when I query the posts to perform the update I want the posts to be ordered like this:

  1. First I want any post that does not have the $TIME postmeta
  2. Then all others, starting from the ones I've updated earlier

These are the query arguments I'm using:

$args = array(
   'post_type' => 'post',
   'post_status' => 'publish',
   'posts_per_page' => '10',
   'meta_query' => array(
      'relation' => 'OR',
       array( 
               'key' => 'TIME_meta_key',
               'compare' => 'EXISTS'
           ),
         array(
               'key' => 'TIME_meta_key',
               'compare' => 'NOT EXISTS',
               'value' => 'xxx'  // I've read this is a bug, so I put a value even if it's ignored
           ),
       ),
   'orderby' => 'TIME_meta_key',
   'order' => 'ASC'
 );

As I said before, the TIME_meta_key value (when exists) is just a UNIX timestamp.

So, as I want to update first the posts that are still not updated, then the ones that have been updated earlier in time, I assume I have to order ASC.

But if I set ASC, this does not work. it keep updating the posts that already have a value in the TIME_meta_key field.

Is this normal or I'm making some stupid mistake?

1 Answer 1

0

You can do this by naming index of meta query, then passing array of these names in orderby parameter

$args = array(
   'post_type' => 'post',
   'post_status' => 'publish',
   'posts_per_page' => '10',
   'meta_query' => array(
      'relation' => 'OR',
      'with_time' => array( 
               'key' => 'TIME_meta_key',
               'compare' => 'EXISTS'
           ),
      'without_time' => array(
               'key' => 'TIME_meta_key',
               'compare' => 'NOT EXISTS',
               /* 'value' => 'xxx'  The bug has been fixed ; */
           ),
       ),
   /* First order posts those does not have meta key then those have meta key in ascending order */
   'orderby' => array(
       'without_time' => 'ASC',
       'with_time' => 'ASC'
   ),
 );

In orderby array first key is without_time then with_time thus it will bring up all the posts first those does not have TIME_meta_key however, these posts will not have order (Will be default based on ID) because meta key does not exist. Then it will join the posts those have meta key TIME_meta_key in ascending order.

So the final outcome will be posts without meta key orderby ID then posts with meta key order by value ascending.

NOTE 1: these syntax are only supported since WordPress version 4.2
NOTE 2: Another bug related to NOT EXIST has been fixed in WordPress 3.9

6
  • thanks for answer Sumit. So I was trying to do something not possibile?
    – bluantinoo
    Apr 5, 2016 at 17:29
  • 1
    Yes it will not work because when you set order by time, first those posts comes up those have time!
    – Sumit
    Apr 5, 2016 at 17:42
  • I imagined that, indeed this is the doubt for I've posted this question. What would happen to posts with the TIME_meta_key empty? Would they be selected at the beginning or be skipped as well? And more generical: empty values can be sorted?
    – bluantinoo
    Apr 5, 2016 at 18:49
  • @bluantinoo I've updated my answer for your queries. And I will say please run this code then only you can see real output!
    – Sumit
    Apr 6, 2016 at 6:27
  • 1
    Finally i got the chance to test it. it works! Thanks @Sumit, and sorry for the delay :)
    – bluantinoo
    Apr 22, 2016 at 11:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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