Question

I have two entities, post and category which is a 1:n relationship.

I have a reference table with two columns, post_id,category_id

The categories table has an id column, a status column and a parent_id column

If a category is a child of another category (n-depth) then it's parent_id is not null.

If a category is online it's status is 1, otherwise it is 0.

What I need to do is find out if a post is visible.

This requires:

Foreach category joined to the post trace up it's tree to the root node (till a category has parent_id == null), if any of those categories have status 0 then that path is considered offline.

If any path is online then the post is considered visible, otherwise it is hidden.

The only way I can think of doing this (as semi-pseudo code) is:

function visible(category_ids){
  categories = //select * from categories where id in(category_ids)
  online = false
  foreach(categories as category){
    if(category.status == 0)
      continue;

    children = //select id from categories where parent_id = category.id
    if(children)
      online = visible(children)
  }
  return online
}

categories = //select c.id from categories c join posts_categories pc on pc.category_id = c.id where pc.post_id = post.id

post.online = visible(categories)

But that could end up being a lot of sql queries, is there a better way?

Was it helpful?

Solution

If nested sets are not an option, I know about the following:

  • If the data is ordered so that children of a parent always follow after it's parent, you can solve this with one database-query over all data by skipping hidden nodes in the output.

This works equally with a sorted nested set, too, the principle has been outlined in this answer however the algorithms about getting the depth do not work and I would suggest a recursive iterator that is able to remove hidden items.

Also if the data is not ordered, you can create a tree structure from the (unsorted) query of all rows like outlined in the answer to Nested array. Third level is disappearing. No recursion needed and you get a structure you can easily output then, I should have covered that for <ul>/<li> html style output in another answer, too.

OTHER TIPS

A classic database vs memory tradeoff. What you are doing is building a tree with leafs in it. To build the tree you need recursive loop the leafs. Coming from a database there are 2 scenarios:

  1. Build the tree recursive with a query for each leaf. You hold 1 tree in memory. That is what you are doing.
  2. Get a flat structure from the database, and build the tree recursive in memory. You hold a flat tree and the real tree in memory. That is your alternative way.

What is better depends on a lot of things: your hardware (disk access vs memory), the size of the tree to name two.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top