7 thoughts on “Not all Post Meta is bad

  1. Pingback: How to vet a plugin for add on development - Austin WordPress Meetup

  2. Hi Tom,

    Let my ask you how would you go about a fast way to query a lists of posts in this situation:

    – We have one hierarchical taxonomy with two parent terms. So they build two branches in the taxonomy tree.
    – Say the viewer is in a term page, in: site.com/parent_term_a/children_term_aa/grandchildren_term_aaa
    – Say grandchildren_term_aaa has a term meta value that relates it with a grandchild from the other big branch: site.com/parent_term_b/children_term_ba/grandchildren_term_bcc.
    – As said before, viewer is in /../grandchildren_term_aaa, and we want to show them links for the term pages of terms that are related, like /../grandchildren_term_bcc.

    So that query should use wp_term_query() to get terms with that term meta value? Or is there a lighter and quicker way?

    So my question is about querying for terms that are in the same taxonomy but in different, distant branches, but they must be related somehow, for example with term meta.


    • In that case you just call get_term_meta since you already know the ID of the current term. The term meta can then hold the value of the other terms ID

      But this all seems overcomplicated. If you want to group things together, use a taxonomy, or better yet, you’re grouping the wrong things.

      For example, instead of grouping the terms ( which are already grouped by parentage ), group the posts, and show a list of terms the posts have. You gain the benefit that your UI is more direct and easier to understand, whereas before it wasn’t clear where the suggestions came from. Is it suggesting A B and C because that person is A B and C? Or is it the term? Why would the parent child relationship have this? It’s confusing.

      You also gain the benefit that the entire thing now requires no manual intervention to set up relatedness.

      For example, we might have a product category, and the user is inside an electric car category. In the above case, I would imagine you have a term meta saying ‘cars’ and want to show other terms that have this term meta. The correct answer is to use a ‘cars’ term as the parent.

      Alternatively, look at the posts inside the electric cars page, and list their categories as suggestions.

      The fundamental anti-pattern here is that you should not be grouping things via meta, be it post meta or term meta, especially if you need to query for them.

      However, it may be that what you’re talking about doesn’t fit into this at all because you’ve removed all context to make it a generic case, and that the actual problem is that the data structure is broken, and something that should be a CPT is actually a taxonomy, and vice versa.

      It’s really difficult to answer when there’s no context as any answer has to fit every use case, which is simply impossible without speaking in the most generic vaguest sense. If you can provide specifics I can be more helpful. The generic case of how to store a group of groups is usually solved by hierarchy/term parents, or refactoring

  3. Hi Tom,

    All that you said is perfectly valid, of course. But let me tell you why I think it doesn’t apply to my case.
    I’ll be specific: ‘hotels’ cpt, ‘locations’ taxonomy.

    The main problem is that there are two types of terms: the first is the admin-terms, like continent, country, region, city. These is the main classification and what provides the url, like site.com/north-america/usa/california/san-francisco.

    The other types are things like ‘tourist-regions’, ‘valleys’ or ‘mountain-ranges’. As you can imagine, there is a million combinations between these terms with the admin-* ones.

    A real case is a resort that belongs to three different countries -yes, this actually exists-, one valley -which covers two of those countries-, two regional parks (of two different countries), one national park (we are lucky, just one country), three tourist regions (which cover five admin-regions) and, of course, one mountain range and two different sub-mountain ranges.

    So, to simplify, let’s just imagine only a second type of terms: natural-locations, like ‘parks’ and ‘valleys’

    Now, the problem is: if viewer is in some country/region page, we need to show them the valleys and parks related to that region. They can click on a valley that covers that region (remember, the valley can cover another region) and, when going to that valley-term page, they can see links to those two regions the valley is in, the one they saw before and a new one.

    I would be happy to simply make more taxonomies for those other types of terms, but then, how one term of a taxonomy could be related to a term of another taxonomy? Parenthood between terms doesn’t work either because a valley is not child of any region or viceversa. Different types of locations can make many combinations with others. Mostly many-to-many.

    It’s easier -I think- to build just one taxonomy with parent terms for every type of location, build the tree and then tell WordPress: hey, this region has this valley. Hey, that region has the same valley and a park. Hey, this park covers two different countries. That’s why I think term meta applies here: relating pages of terms that are in distant branches of the taxonomy tree.

    Then, for every term page, I can query which terms are related for this location-item and go to their pages.

    The only alternative I can think of is something you’ve mentioned: if the viewer is in a specific region term page, they’re viewing a list of hotels (posts). So let’s show them the list of other terms (be one taxonomy, be others) that those hotels belong to.

    But that would be a complex and expensive query, right?

    Thanks and sorry for the convoluted exposition.

    • Keep in mind that at the end of the day, the taxonomy table was deliberately optimised for finding posts XYZ where we know something about them ABC, where ABC is a term, and that the post meta table was optimised for finding key/value pairs of a known post.

      As for:

      continent, country, region, city etc

      A location taxonomy sounds great, and maybe you can attach a term meta named `park`. Then you can assign another tag to the post `in-park` when the term is attached. Sure the two aren’t directly attached but is that really necessary with the right filters? And do you really require it? As long as the user and the UI are correct I don’t see the need for absolute precision here.

      On top of that, it’s a trade off, where the choice of only storing 1 copy of data, and making sure it is incredibly accurate and semantically correct, ensures problems. This is a rabbit hole that you could fall down forever, and apply to everything. E.g. we can store a price in post meta, but how do we store the currency in such a way that it’s attached? We can’t have post meta meta?

      Keep in mind that sometimes the problem is what you want to store, and sometimes the problem is exactly that, a problem to be solved.

      And finally, it’s what you’re going to do with the data that has more of an impact on how to store it than what is ‘supposed’ to be done. E.g. it doesn’t make sense to store exact prices as terms, but if you’re Amazon, it might.

  4. Hi Tom,

    “Post meta is optimised for direct accesses with a known post ID. If you’re trying to search for posts with or without certain meta values, you should use a taxonomy instead.”

    There are some situations we can’t use taxonomy like votes for posts, prices, dates (not the post published date), etc.

    But it is requirements that you able to sort posts by votes, prices, dates, etc.

    What can we do in this situation.


    • > There are some situations we can’t use taxonomy like votes for posts, prices, dates (not the post published date), etc.

      That’s not true, you can store intermediate values. The data in your DB isn’t just a record of truth, it’s a data store. You’re perfectly able to store a term saying that the price is “between $5 and $10”, and if that speeds things up great! You’re perfectly capable of storing calculated values to save time, so why store just the precision version of the data?

      > But it is requirements that you able to sort posts by votes, prices, dates, etc.

      For dates, those posts have fields in the post that can and should be used. A lot of people use meta instead or UI reasons, or because future dates don’t show, but those are different problems with their own solutions, e.g. a `pre_get_posts` filter to fix the future dates issue. That way dates relies on an indexed value, which is faster than post meta, and even faster than taxonomies.

      If you can store votes or prices in the menu order field then you can gain the same boost. Else, store approximate values in terms for filtering, and sort on post meta. Sometimes sorting on post meta is unavoidable, in which case if you want to avoid the slowdown, elastic search would be the best bet.

      Remember, the trade off is yours to make, I’m simply making you aware that there’s one being made, and that there is a price being paid that most people are unaware of

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.