Like I said below, I don't have much experience with database design. I don't really have any clue how to write a design document. But I want to describe the design I've come up with and see if I can make it sound as good as it appears to me to be.
The thinking behind this is as follows: I have a lot of text records ("posts") which I want to classify by subject. I've done this, just like every other blog around, by using keywords -- if I tag a post with "food" say, or "singing", then it will show up when somebody looks at the site filtering for that subject. This is implemented with a simple search through the list of keywords on each post; not particularly fast but that's not a major problem in the context of my low-traffic site.
But when I was putting the new software together, I had the idea that it would be great if, when somebody looked at the blog filtering for "food", they would see a little sidebar explaining what I write about when I write about food, and maybe some links to food sites I like etc. And more to the point, when somebody filters for "book:namered" (which is how I've been tagging my reading posts, "book:" and then a short identifier for the title), they would see up top that the posts were about My Name is Red by Orhan Pamuk, links to some outside reviews, links to Amazon and Abebooks, maybe a list of other of Pamuk's books that I have written about. So that is the problem I am trying to solve; and I think my solution is a pretty good one.
First, simple keywords, like "food" and "singing". This is pretty easy; I have a table keyword with columns tag and description -- the description is what will be displayed in the sidebar when somebody filters by the tag. And I have a table (which I decided to name categories, for reasons that will soon become apparent) with two columns, postid and keyword -- I can join this table with posts when I want to do a filtering operation.
Now what about the complex keywords like "book:namered", which include a class and an instance? Well check it out: every time I add a keyword which has a new class, I can just add a column to the categories table with the class name as the column name. And add a table with that name, which looks the same as the keyword table. And think of simple keywords as a special case of complex keywords, as if they had "keyword:" in front of them. So if somebody requests a filter for "book:namered", I can query from "posts JOIN categories ON posts.id = categories.postid JOIN book ON categories.book = book.tag" where book.tag = "namered". This will work for movies, projects, whatever. But the really cool thing is, I can add whatever columns I want to the book table and write a custom script to display the data associated with the tag "namered" in my sidebar.
Consider these three requests:
- SELECT posts.* FROM posts JOIN categories ON posts.id = categories.postid WHERE categories.book = 'namered';
(This query would be represented by the keyword "book:namered".)
- SELECT DISTINCT posts.* FROM posts JOIN categories ON posts.id = categories.postid JOIN book ON categories.book = book.tag;
(This query would be represented by the keyword "book:".)
- SELECT posts.* FROM posts JOIN categories ON posts.id = categories.postid JOIN book ON categories.book = book.tag WHERE book.author = 'pamuk';
(This query would be represented by the keyword "book:author:pamuk".)
The first query will bring back all posts about My Name is Red. The second query will bring back all posts about reading any book. The third query will bring back all posts about reading any book by Orhan Pamuk. And all this is pretty easy to automate! It's all nearly in place!
The next step, which will be a bit of effort to keep it elegant but totally within reach, is to create an administrative page for writing scripts to render an informative sidebar based on the column data contained in, say, the "namered" record in books.