BlogDiagram.png
  1. User Table

In this section, we will design the User Table to store user information of all the post authors. The same table can be used to relate the post authors so that all the authors can manage their own posts. Below mentioned is the description of all the columns of the User Table.

Column Name Description
Id The unique id to identify the user.
First Name The first name of the user.
Middle Name The middle name of the user.
Last Name The last name of the user.
Mobile The mobile number of the user. It can be used for login and registration purposes.
Email The email of the user. It can be used for login and registration purposes.
Password Hash The password hash generated by the appropriate algorithm. We must avoid storing plain passwords.
Registered At This column can be used to calculate the life of the user with the blog.
Last Login It can be used to identify the last login of the user.
Intro The brief introduction of the Author to be displayed on each post.
Profile The author details to be displayed on the Author Page.

--
-- Table structure for table `user`,
-- Change to author as user is a reserved
--

DROP TABLE IF EXISTS blogger.author;
CREATE TABLE blogger.author (
  id SERIAL PRIMARY KEY,
  firstName varchar(50) DEFAULT NULL,
  middleName varchar(50) DEFAULT NULL,
  lastName varchar(50) DEFAULT NULL,
  mobile varchar(15) UNIQUE,
  email varchar(50) UNIQUE,
  passwordHash varchar(32) NOT NULL,
  registeredAt timestamp NOT NULL,
  lastLogin timestamp DEFAULT NULL,
  intro text,
  profile text
);

  1. Post Table

In this section, we will design the Post Table to store the post data. Below mentioned is the description of all the columns of the Post Table.

Column Name Description
Id The unique id to identify the post.
Author Id The author id to identify the post author.
Parent Id The parent id to identify the parent post. It can be used to form the table of content of the parent post of series.
Title The post title to be displayed on the Post Page and the lists.
Meta Title The meta title to be used for browser title and SEO.
Slug The post slug to form the URL.
Summary The summary of the post to mention the key highlights.
Published It can be used to identify whether the post is publicly available.
Created At It stores the date and time at which the post is created.
Updated At It stores the date and time at which the post is updated.
Published At It stores the date and time at which the post is published.
Content The column used to store the post data.
--
-- Table structure for table `post`
--

DROP TABLE IF EXISTS post;
CREATE TABLE post (
  id BIGINT NOT NULL,
  author_id BIGINT NOT NULL,
  parent_id BIGINT,
  title VARCHAR(75) NOT NULL,
  meta_title VARCHAR(100),
  slug VARCHAR(100) NOT NULL,
  summary TEXT,
  published BOOLEAN NOT NULL DEFAULT FALSE,
  created_at TIMESTAMP NOT NULL,
  updated_at TIMESTAMP,
  published_at TIMESTAMP,
  content TEXT,
  PRIMARY KEY (id),
  CONSTRAINT fk_post_parent FOREIGN KEY (parent_id) REFERENCES post(id),
  CONSTRAINT fk_post_user FOREIGN KEY (author_id) REFERENCES "user"(id)
);
  1. Post Meta -> post_meta

The Post Meta Table can be used to store additional information of a post including the post banner URL etc. Below mentioned is the description of all the columns of the Post Meta Table.

Column Name Description
Id The unique id to identify the post meta.
Post Id The post id to identify the parent post.
Key The key identifying the meta.
Content The column used to store the post data.
--
-- Table structure for table `post_meta`
--

DROP TABLE IF EXISTS "post_meta";

CREATE TABLE "post_meta" (
  "id" BIGSERIAL NOT NULL,
  "postId" BIGINT NOT NULL,
  "key" VARCHAR(50) COLLATE "pg_catalog"."default" NOT NULL,
  "content" TEXT COLLATE "pg_catalog"."default",
  CONSTRAINT "pk_post_meta_id" PRIMARY KEY ("id"),
  CONSTRAINT "uq_post_meta" UNIQUE ("postId", "key"),
  CONSTRAINT "fk_meta_post" FOREIGN KEY ("postId") REFERENCES "post" ("id")
);
COLLATE is a clause in SQL used to define the collation (i.e., the set of rules governing how string values are sorted and compared) for a character data type in a database. In the given SQL statement, COLLATE "pg_catalog"."default" is specifying the collation for the key column as the default collation for the PostgreSQL catalog.

By default, if no COLLATE clause is specified, the collation of the column is inherited from the database's default collation. The COLLATE clause can be used to override the default collation and specify a specific collation for the column. This can be useful when working with multilingual databases where different character sets and collations are needed to handle text data correctly.
  1. Post Comment --> post_comment

Post Comment Table to is to store the post comments. Below mentioned is the description of all the columns of the Post Comment Table.

Column Name Description
Id The unique id to identify the post comment.
Post Id The post id to identify the parent post.
Parent Id The parent id to identify the parent comment.
Title The comment title.
Published It can be used to identify whether the comment is publicly available.
Created At It stores the date and time at which the comment is submitted.
Published At It stores the date and time at which the comment is published.
Content The column used to store the comment data.
--
-- Table structure for table `post_comment`
--

DROP TABLE IF EXISTS post_comment;
CREATE TABLE post_comment (
  id BIGINT NOT NULL,
  post_id BIGINT NOT NULL,
  author_id BIGINT,
  parent_id BIGINT,
  created_at TIMESTAMP NOT NULL,
  updated_at TIMESTAMP,
  content TEXT,
  PRIMARY KEY (id),
  CONSTRAINT fk_comment_post FOREIGN KEY (post_id) REFERENCES post(id),
  CONSTRAINT fk_comment_user FOREIGN KEY (author_id) REFERENCES "user"(id),
  CONSTRAINT fk_comment_parent FOREIGN KEY (parent_id) REFERENCES post_comment(id)
);
  1. Category -->category

We will design the Category Table and Post Category Table to store the post categories and their mappings. Below mentioned is the description of all the columns of the Category Table.

Column Name Description
Id The unique id to identify the category.
Parent Id The parent id to identify the parent category.
Title The category title.
Meta Title The meta title to be used for browser title and SEO.
Slug The category slug to form the URL.
Content The column used to store the category data.
--
-- Table structure for table `category`
--

DROP TABLE IF EXISTS category;
CREATE TABLE category (
  id BIGINT NOT NULL,
  parent_id BIGINT,
  title VARCHAR(75) NOT NULL,
  meta_title VARCHAR(100),
  slug VARCHAR(100) NOT NULL,
  content TEXT,
  PRIMARY KEY (id)
);
  1. Post Category Table -> post_category
Column Name Description
Post Id The post id to identify the post.
Category Id The category id to identify the category.
--
-- Table structure for table `post_category`
--

DROP TABLE IF EXISTS post_category;
CREATE TABLE post_category (
  post_id BIGINT NOT NULL,
  category_id BIGINT NOT NULL,
  PRIMARY KEY (post_id, category_id),
  CONSTRAINT fk_pc_post FOREIGN KEY (post_id) REFERENCES post(id),
  CONSTRAINT fk_pc_category FOREIGN KEY (category_id) REFERENCES category(id)
);

Tag Table and Post Tag Table

Similar to the category and post category tables, we can design the Tag Table and Post Tag Table. The major differences between the Category and Tag are listed below.

The parentId column is not required in the Tag Table.
The count of categories remains low since these can be used to form the Main Menu for navigational purposes. The tags can be more as compared to categories.
Both categories and tags can be used to relate the posts.
One should assign only a few categories to a post whereas tags count can be more.

  1. Tag --> tag
--
-- Table structure for table "tag"
--

DROP TABLE IF EXISTS "tag";
CREATE TABLE "tag" (
  "id" BIGINT NOT NULL GENERATED ALWAYS AS IDENTITY,
  "title" VARCHAR(75) COLLATE "pg_catalog"."default" NOT NULL,
  "metaTitle" VARCHAR(100) COLLATE "pg_catalog"."default",
  "slug" VARCHAR(100) COLLATE "pg_catalog"."default" NOT NULL,
  "content" TEXT COLLATE "pg_catalog"."default",
  PRIMARY KEY ("id")
) ;
  1. Post Tag --> post_tag
--
-- Table structure for table `post_tag`
--

DROP TABLE IF EXISTS "post_tag";
CREATE TABLE "post_tag" (
  "postId" bigint NOT NULL,
  "tagId" bigint NOT NULL,
  PRIMARY KEY ("postId","tagId"),
  CONSTRAINT "fk_pt_post" FOREIGN KEY ("postId") REFERENCES "post" ("id"),
  CONSTRAINT "fk_pt_tag" FOREIGN KEY ("tagId") REFERENCES "tag" ("id")
);
CREATE INDEX "idx_pt_tag" ON "post_tag" ("tagId");
CREATE INDEX "idx_pt_post" ON "post_tag" ("postId");