0

I have the goal of getting n custom posts from a query.
I have 4 values stored in ACF. If I can find n posts where all these values are the same as the current post's, then I want to return those n.
If I can only find, for instance, 5 post where the ACF values are the same then I want those and the remaining n-5 to share 3 ACF values, then those sharing 2, then 1 and then just anything if I haven't found n posts yet.

I've managed to do this, but it seems like a pretty stupid way of doing it.

function queryRelatedMedia($array, $post_id, $postLimit, $genre = null, $rating = null){
    $cCount = array_search(end($array), $array);
    $cCount = $cCount? $cCount : 0;
    $query = new WP_Query(.....); // Some relevant query
    while($query -> have_posts() and $cCount < $postLimit){
        $query -> the_post();

        if($post_id == get_the_id()){ continue; }
        if($rating and get_field("rating") != $rating){ continue; }
        if($genre and get_field("genre") != $genre){ continue; }

        $resArr = array(.....); // Store relevant data in array
        if(!array_search($resArr, $array)){
            array_push($array, $resArr);
            $cCount++;
        }
    }
}

$queryArray = queryRelatedMedia(array(),     $post_id, $amount, $genre, $rating);
$queryArray = queryRelatedMedia($queryArray, $post_id, $amount, $genre);
$queryArray = queryRelatedMedia($queryArray, $post_id, $amount);

So I run the query first with the most specific checks. Then look at how large the array of posts is, if it's not n then I run it again with 1 parameter less.

Is there a smarter (more efficient) way of doing this?

4
  • Did you happen to try using meta query? ACF fields are stored as post meta and you can directly use meta query with AND operator to get all the matching post directly instead of filtering it later with while loop. advancedcustomfields.com/resources/query-posts-custom-fields Also not sure why you choose ACF for this purpose unless it's an existing website, it seems easier with taxonomy.
    – Kumar
    Nov 25 at 9:49
  • @Kumar How would I avoid querying 3 times by specifying the meta values as part of the query? And I use ACF because that's what I know how to use. From what I know using taxonomies won't fit.
    – Fluxian
    Nov 25 at 9:56
  • For current post get all [ACF] key => value; Build a WP_Query meta_query relation OR for given key => value; This returns all the posts with at least one matching key => value; Loop over ids from above result; build an array of post id and key => value pair; You have array current_post[] of key =>value , and matching_post[] containing key=>value for all the matching posts; 1. Intersect current_post[] and matching_post[] returns all post with same key value. Remove the posts ids from matching_post[]. 2. And then subsequently delete keys from current_post[], and intersect again
    – Kumar
    Nov 25 at 10:17
  • @Kumar That doesn't sound like what I'm trying to do. Can you write it out in an answer so it's easier to understand?
    – Fluxian
    Nov 25 at 10:26
0

This answer just explains a possible approach and doesn't provides with detailed code.

The following approach relies more on PHP for filtering the results instead of multiple WP_Query, it uses a single WP_Query along with multiple get_post_meta() calls.

Step 1:

For the current post build an array using get_field() or get_post_meta() with all the necessary key and values:

$current_post = array(
   k1 => v1, 
   k2 => v2, 
   k3 =>v3 
);

Step 2:

Get all the post Ids using WP_Query(meta_query) which has at least one matching key,value pair.

WP_Query[
'meta_query'    => array(
        'relation'      => 'OR',
        array(
            'key'       => 'k1',
            'value'     => 'v1',
            'compare'   => '='
        ),
        array(
            'key'       => 'k2',
            'value'     => 'v2',
            'compare'   => '='
        ),
        array(
            'key'       => 'k3',
            'value'     => 'v3',
            'compare'   => '='
        )
    )
]

Step 3:

For all the post ids from above result; iterate and build an array matching_posts with all the key, values;

$matching_posts = array(
     post_id_1 => array ( 
       k1 => v1, 
       k2 => v2, 
       k3 =>v3 
     ),
     post_id_2 => array ( 
       k1 => v1, 
       k2 => v2, 
       k3 =>v3 
     )
     .
     .
     .
    );

Step 4:

4.1 :

Use php array functions[array_intersect] to get related post ids for $current_post[];

Remove related post ids from $matching_posts[]

4.2 Remove the last key=>value from $current_post[]; and repeat 4.1

Repeat 4.2

This would give you 3 sets of array:

  1. Post ids with all key=>value(3) in common,
  2. and then 2 same key=>value
  3. And then posts which has only single key=>value in common.

For the other part of question: getting at least n posts for the current post, you can have a simple query to get n - x posts which excludes all the post above. Where x is the sum of all matching posts.

4
  • Thanks for the answer. I'll digest this a bit and see if I can get it to work! :)
    – Fluxian
    Nov 25 at 10:54
  • Sure, If the number of posts are going to be limited then using multiple WP_Query should be just fine.
    – Kumar
    Nov 25 at 10:56
  • 1
    I ended up figuring it out, not exactly based on your answer but parts of it made me realise what's possible with wp_query that I hadn't cognised. Thanks a lot! :)
    – Fluxian
    Nov 27 at 13:05
  • That's great, happy that it was helpful in some way.
    – Kumar
    Nov 29 at 3:13

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.