Here's the TLDR: Is is possible to get all meta keys from a specific CPT without a database hit for each post?

If so, how can I do this the Wordpress way?

This seems like a simple thing to do ( at least from a database perspective ) but I'm looking for the Wordpress way to get multiple post_meta values from a bunch of CPTs. Example:

Every Product Custom Post Type has the following fields ( plus many more ) which holds discrete pieces of information:

  • _ns_research_document
  • _ns_monograph_document
  • _ns_profile_document

Essentially, I want a list of ALL Research Docs, Monographs and Profile Docs. Currently this site has 72 product posts, but other sites this will be used on have over a thousand.

I assume there's a way to do this with wordpress methods that doesn't involve [at least] 73 calls ( one for all posts, and then get_post_meta inside the loop ).

The general solution I've found suggest a get_post_meta inside a foreach loop: https://stackoverflow.com/questions/14699686/custom-post-type-loop-only-displays-first-post-meta-data

But in this case, I really only want the meta_values in an array for a specific CPT.

Database Logic tells me that this should be only 2 queries... one on the post_meta table, one on the the posts table. It might include some joins, but still a rather inexpensive couple of queries.

2 Answers 2


Okay, so long story short... there's no built-in wordpress way to Query the meta-data directly, but in the interests of helping others, essentially you need to do it the old-fashioned way... using SQL:

I'm going to do up a post which I'll link to... but essentially it involves straight SQL and $wpdb->get_results and some PHP loops.

To get all the values for _ns_research_document, _ns_monograph_document, and _ns_profile_document I did this:

// prepare SQL
$wpdb->prepare("SELECT DISTINCT post_id, meta_key, meta_value"
 ." FROM " $wpdb->postmeta 
 ." WHERE meta_key IN ( '_ns_research_document', '_ns_monograph_document', '_ns_profile_document') "
 ." ORDER BY post_id, meta_key ASC" );

// call DB
$results = $wpdb->get_results( $sql );

It returns an array with an array for each row, which I was able to loop through and recategorize. Kind of surprising I couldn't find a WP way to do this without SQL, but such is life.

Note that if you wanted to be sure to ONLY get product posts, you'd probably have to do an INNER JOIN in your sql.


I suggest to use this function to bring all post meta fields with one query: https://codex.wordpress.org/Function_Reference/get_post_custom

Use it inside loop, for query all post fields, it's return an array of all post fields.

  • Doesn't this accomplish the same thing as get_post_meta()? If this has to be called in the loop. it will have to be called 72 times, once for each product Commented Aug 9, 2016 at 19:37
  • Get post meta called once per one field. Get post custom called once and bring all custom fields values
    – vol4ikman
    Commented Aug 9, 2016 at 19:41
  • Interesting. If I don't specify the field name, though... doesn't get_post_meta pull all the post_meta in one call? If not, that's bizarre. Although, i will say that using get_post_custom appears to pull only the fields that you need, so it's probably slightly more efficient. Still though, it's 73 calls either way in the end if I'm calling this from within the loop. Commented Aug 9, 2016 at 22:35

Your Answer

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

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