最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

PostgreSQL實現(xiàn)一個通用標簽系統(tǒng)

 更新時間:2019年01月13日 15:02:39   作者:lanzhiheng  
這篇文章主要給大家介紹了關于利用PostgreSQL實現(xiàn)一個通用標簽系統(tǒng)的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

前言

對資源打標簽在建站過程中是很常見的需求,有些時候我們需要給文章打標簽,有些時候我們需要給用戶打標簽。實現(xiàn)一個標簽系統(tǒng)其實并不難,其本質(zhì)就是一個多對多的關系-我可以對同一篇博客打多個標簽,同時也可以把一個標簽打到不同的博客身上。這篇文章主要通過分析標簽系統(tǒng)的原理,并用PostgreSQL來實現(xiàn)一個能夠為多種資源打標簽的標簽系統(tǒng)。

1. 單一資源標簽系統(tǒng)

先從單一資源開始,所謂單一資源便是,我們只給一種數(shù)據(jù)資源打標簽。假設我們需要給博客文章打標簽,那么我們需要構(gòu)建以下幾個表:

  • 文章表posts,用于存儲文章的基本信息。
  • 標簽表tags,用于存儲標簽的基本信息。
  • 標簽-文章表tags_posts,存儲雙方的id并形成多對多的關系。

表設計圖大概是

先進入數(shù)據(jù)庫引擎并創(chuàng)建對應的數(shù)據(jù)庫

postgres=# create database blog;
CREATE DATABASE

postgres=# \c blog;
blog=#

通過SQL語句創(chuàng)建上面所提到的數(shù)據(jù)表

CREATE TABLE posts (
 id    SERIAL,
 body   text,
 title   varchar(80)
);

CREATE TABLE tags (
 id    SERIAL,
 name   varchar(80)
);

CREATE TABLE tags_posts (
 id    SERIAL,
 tag_id   integer,
 post_id   integer
);

每個表都只是包含了該資源最基礎的字段, 到這一步為止其實已經(jīng)構(gòu)建好了一個最簡單的標簽系統(tǒng)了。接下來則是填充數(shù)據(jù),我的策略是添加兩篇文章,五個標簽,給標題為Ruby的文章打上language標簽,給標題為Docker的文章打上container的標簽,兩篇文章都要打上tech標簽

-- 填充文章數(shù)據(jù)
INSERT INTO posts (body, title) VALUES ('Hello Ruby', 'Ruby');
INSERT INTO posts (body, title) VALUES ('Hello Docker', 'Docker');

-- 填充標簽數(shù)據(jù)
INSERT INTO tags (name) VALUES ('language');
INSERT INTO tags (name) VALUES ('container');
INSERT INTO tags (name) VALUES ('tech');

-- 為相關資源打上標簽
INSERT INTO tags_posts (tag_id, post_id) VALUES ((SELECT id FROM tags WHERE name = 'container'), (SELECT id FROM posts WHERE title = 'Docker'));
INSERT INTO tags_posts (tag_id, post_id) VALUES ((SELECT id FROM tags WHERE name = 'tech'), (SELECT id FROM posts WHERE title = 'Docker'));
INSERT INTO tags_posts (tag_id, post_id) VALUES ((SELECT id FROM tags WHERE name = 'tech'), (SELECT id FROM posts WHERE title = 'Ruby'));
INSERT INTO tags_posts (tag_id, post_id) VALUES ((SELECT id FROM tags WHERE name = 'language'), (SELECT id FROM posts WHERE title = 'Ruby'));

然后分別查詢兩篇文章都被打上了什么標簽。

blog=# SELECT tags.name FROM tags, posts, tags_posts WHERE tags.id = tags_posts.tag_id AND posts.id = tags_posts.post_id AND posts.title = 'Ruby';
 name
----------
 language
 tech
(2 rows)

blog=# SELECT tags.name FROM tags, posts, tags_posts WHERE tags.id = tags_posts.tag_id AND posts.id = tags_posts.post_id AND posts.title = 'Docker';
 name
-----------
 container
 tech
(2 rows)

兩篇文章都被打上期望的標簽了,相關的語句有點長,一般生產(chǎn)線上不會這樣直接操作數(shù)據(jù)庫。各種編程語言的社區(qū)一般都對這種數(shù)據(jù)庫操作進行了封裝,這為編寫業(yè)務代碼帶來了不少的便利性。

2. 為多種資源打標簽

如果只需要對一個數(shù)據(jù)表打標簽的話,依照上面的邏輯來設計表已經(jīng)足夠了。但是現(xiàn)實世界往往沒那么簡單,假設除了要給博客文章打標簽之外,還需要給用戶表打標簽呢?我們需要把表設計得更靈活一些。如果繼續(xù)用tags表來存標簽數(shù)據(jù),為了給用戶打標簽還得另外建一個名為tags_users的表來存儲標簽與用戶數(shù)據(jù)之間的關系。

但更好的做法應該是采用名為多態(tài)的設計。創(chuàng)建關聯(lián)表taggings,這個關聯(lián)表除了會存儲關聯(lián)的兩個id之外,還會存儲被打上標簽的資源類型,我們根據(jù)類型來區(qū)分被打標簽的到底是哪種資源,這會在每條記錄上多存了類型數(shù)據(jù),不過好處就是可以少建表,所有的標簽關系都通過一個表來存儲。

Ruby比較流行的標簽系統(tǒng)ActsAsTaggableOn 就沿用了這個設計,不過它的類型字段直接存的是對應資源的類名,或許是為了更方便編程吧,數(shù)據(jù)大概如下:

naive_development=# select id, tag_id, taggable_type, taggable_id from taggings;
 id | tag_id | taggable_type  | taggable_id
----+--------+----------------------+-------------
 1 |  1 | Refinery::Blog::Post |   1
 2 |  2 | Refinery::Blog::Post |   1
 3 |  3 | Refinery::Blog::Post |   1

先通過taggable_type獲取類名,然后再利用taggable_id的數(shù)據(jù)就能準確獲取相關的資源了。

a. 修改原表

表設計圖大概如下

這里我不重新建表了,而直接修改原有的表,并進行數(shù)據(jù)遷移

  • 增加type字段用于存儲資源類型。
  • 把原來的數(shù)據(jù)表改名為更通用的名字taggings。
  • 把原來的post_id字段改成更通用的名字taggable_id。
  • 給原有的資源填充數(shù)據(jù),type字段統(tǒng)一填數(shù)據(jù)post。
ALTER TABLE tags_posts ADD COLUMN type varchar(80);
ALTER TABLE tags_posts RENAME TO taggings;
ALTER TABLE taggings RENAME COLUMN post_id TO taggable_id;
UPDATE taggings SET type='post';

b. 添加用戶

在給用戶打標簽之前先創(chuàng)建用戶表,并填充數(shù)據(jù)

-- 創(chuàng)建簡單的用戶表
CREATE TABLE users (
 id    SERIAL,
 username  varchar(80),
 age    integer
);


-- 添加一個名為lan的用戶,并添加兩個相關的標簽

INSERT INTO users (username, age) values ('lan', 26);

INSERT INTO tags (name) VALUES ('student');
INSERT INTO tags (name) VALUES ('programmer');

c. 給用戶打標簽

接下來需要給用戶lan打上標簽,對原有的SQL語句做一些調(diào)整,并在打標簽的時候把type字段填充為user。

INSERT INTO taggings (tag_id, taggable_id, type) VALUES ((SELECT id FROM tags WHERE name = 'student'), (SELECT id FROM users WHERE username = 'lan'), 'user');

INSERT INTO taggings (tag_id, taggable_id, type) VALUES ((SELECT id FROM tags WHERE name = 'programmer'), (SELECT id FROM users WHERE username = 'lan'), 'user');

上述的SQL語句為用戶打上了student以及programmer兩個標簽。

d. 查看標簽情況

為了完成這個任務我們依然要聯(lián)合三張表進行查詢,同時還要約束type的類型

用戶名為lan的用戶被打上的所有標簽

blog=# SELECT tags.name FROM tags, users, taggings WHERE tags.id = taggings.tag_id AND users.id = taggings.taggable_id AND taggings.type = 'user' AND users.username = 'lan';

 name
------------
 student
 programmer
(2 rows)

標題為Ruby的文章被打上的所有標簽

blog=# SELECT tags.name FROM tags, posts, taggings WHERE tags.id = taggings.tag_id AND posts.id = taggings.taggable_id AND taggings.type = 'post' AND posts.title = 'Ruby';

 name
----------
 language
 tech

OK,都跟預期一樣,現(xiàn)在的標簽系統(tǒng)就比較通用了。

總結(jié)

本文通過PostgreSQL的基礎語句來構(gòu)建了一個標簽系統(tǒng)。實現(xiàn)了一個標簽系統(tǒng)其實并不難,各個語言的社區(qū)應該都有相關的集成。本人也就是想拋開編程語言,從數(shù)據(jù)庫層面來剖析一個標簽系統(tǒng)的基本原理。

PS: 另外推薦一個比較好用的Model Design工具dbdiagram,可以用文本的方式對數(shù)據(jù)表進行設計,邊設計邊預覽。最后還能以PNG,PDF甚至SQL源文件的形式導出。本文的數(shù)據(jù)表配圖均由用該軟件制作。

好了,以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。

相關文章

  • Postgresql的日志配置教程詳解

    Postgresql的日志配置教程詳解

    這篇文章主要介紹了Postgresql的日志配置教程詳解,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-01-01
  • Visual Studio Code(VS Code)查詢PostgreSQL拓展安裝教程圖解

    Visual Studio Code(VS Code)查詢PostgreSQL拓展安裝教程圖解

    這篇文章主要介紹了Visual Studio Code(VS Code)查詢PostgreSQL拓展安裝教程,本文通過圖文并茂的形式給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-01-01
  • PostgreSQL中的N''和::bpchar使用

    PostgreSQL中的N''和::bpchar使用

    文章主要介紹了在SQL中不同字符串類型的使用和區(qū)別,包括N'、::bpchar、VARCHAR(n)、CHAR(n)和TEXT等,并通過示例展示了它們在查詢結(jié)果中的表現(xiàn)
    2025-01-01
  • PostgreSQL標準建表語句分享

    PostgreSQL標準建表語句分享

    這篇文章主要介紹了PostgreSQL標準建表語句分享,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • Postgresql自定義函數(shù)詳解

    Postgresql自定義函數(shù)詳解

    這篇文章主要介紹了Postgresql自定義函數(shù)詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • postgresql 計算距離的實例(單位直接生成米)

    postgresql 計算距離的實例(單位直接生成米)

    這篇文章主要介紹了postgresql 計算距離的實例(單位直接生成米),具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-01-01
  • 基于PostgreSQL密碼重置操作

    基于PostgreSQL密碼重置操作

    這篇文章主要介紹了基于PostgreSQL密碼重置操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-01-01
  • postgresql 循環(huán)函數(shù)的簡單實現(xiàn)操作

    postgresql 循環(huán)函數(shù)的簡單實現(xiàn)操作

    這篇文章主要介紹了postgresql 循環(huán)函數(shù)的簡單實現(xiàn)操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-01-01
  • 最新評論

    和静县| 长治市| 武乡县| 长宁区| 金堂县| 靖远县| 二连浩特市| 滨海县| 长海县| 彰化市| 颍上县| 内黄县| 巴青县| 武山县| 上蔡县| 峡江县| 广平县| 理塘县| 鄂尔多斯市| 西乌| 赤峰市| 和龙市| 大悟县| 伊金霍洛旗| 虞城县| 泽州县| 当阳市| 东乌珠穆沁旗| 陵水| 黄浦区| 嫩江县| 金湖县| 遂平县| 唐河县| 浦县| 嘉峪关市| 泰安市| 东安县| 娄底市| 长汀县| 沭阳县|