欧美阿v视频在线大全_亚洲欧美中文日韩V在线观看_www性欧美日韩欧美91_亚洲欧美日韩久久精品

主頁 > 知識庫 > PostgreSQL實現一個通用標簽系統

PostgreSQL實現一個通用標簽系統

熱門標簽:重慶自動外呼系統定制 打電話智能電銷機器人授權 漯河外呼電話系統 地圖標注和圖片名稱的區別 海豐有多少商家沒有地圖標注 辦公外呼電話系統 外呼調研系統 合肥公司外呼系統運營商 美容工作室地圖標注

前言

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

1. 單一資源標簽系統

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

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

表設計圖大概是

先進入數據庫引擎并創建對應的數據庫

postgres=# create database blog;
CREATE DATABASE

postgres=# \c blog;
blog=#

通過SQL語句創建上面所提到的數據表

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
);

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

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

-- 填充標簽數據
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)

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

2. 為多種資源打標簽

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

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

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

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的數據就能準確獲取相關的資源了。

a. 修改原表

表設計圖大概如下

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

  • 增加type字段用于存儲資源類型。
  • 把原來的數據表改名為更通用的名字taggings。
  • 把原來的post_id字段改成更通用的名字taggable_id。
  • 給原有的資源填充數據,type字段統一填數據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. 添加用戶

在給用戶打標簽之前先創建用戶表,并填充數據

-- 創建簡單的用戶表
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語句做一些調整,并在打標簽的時候把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. 查看標簽情況

為了完成這個任務我們依然要聯合三張表進行查詢,同時還要約束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,都跟預期一樣,現在的標簽系統就比較通用了。

總結

本文通過PostgreSQL的基礎語句來構建了一個標簽系統。實現了一個標簽系統其實并不難,各個語言的社區應該都有相關的集成。本人也就是想拋開編程語言,從數據庫層面來剖析一個標簽系統的基本原理。

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

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

您可能感興趣的文章:
  • Windows下PostgreSQL安裝圖解
  • PostgreSQL 安裝和簡單使用
  • PostgreSQL 創建表分區
  • Postgresql ALTER語句常用操作小結
  • PostgreSQL新手入門教程

標簽:烏海 來賓 錦州 株洲 蚌埠 衡陽 珠海 晉城

巨人網絡通訊聲明:本文標題《PostgreSQL實現一個通用標簽系統》,本文關鍵詞  PostgreSQL,實現,一個,通用,;如發現本文內容存在版權問題,煩請提供相關信息告之我們,我們將及時溝通與處理。本站內容系統采集于網絡,涉及言論、版權與本站無關。
  • 相關文章
  • 下面列出與本文章《PostgreSQL實現一個通用標簽系統》相關的同類信息!
  • 本頁收集關于PostgreSQL實現一個通用標簽系統的相關信息資訊供網民參考!
  • 推薦文章
    欧美阿v视频在线大全_亚洲欧美中文日韩V在线观看_www性欧美日韩欧美91_亚洲欧美日韩久久精品
  • <rt id="w000q"><acronym id="w000q"></acronym></rt>
  • <abbr id="w000q"></abbr>
    <rt id="w000q"></rt>
    一级日本不卡的影视| 日本美女视频网站| 蜜臀久久99精品久久久久久| 欧美一级理论片| 亚洲成人av免费| 任你躁av一区二区三区| 欧美亚洲综合在线| 亚洲精品第一国产综合野| 99久久久久久| 欧美三级视频在线观看| 一区二区在线观看免费视频播放| 99久久久久久| 欧美午夜在线一二页| 亚洲激情网站免费观看| 韩国av中国字幕| 欧美高清精品3d| 日日摸夜夜添夜夜添国产精品| 国产精品成人无码专区| 欧美一区二区视频观看视频| 秋霞国产午夜精品免费视频 | 精品盗摄一区二区三区| 美女在线一区二区| 色屁屁草草影院ccyy.com| 国产婷婷一区二区| 成人国产精品免费观看| 色av综合在线| 亚洲电影一级片| 免费a在线观看播放| 精品sm在线观看| 国产精品一区二区三区乱码| 国产人妻精品一区二区三区不卡| 亚洲人成影院在线观看| 无码人妻一区二区三区精品视频| 欧美一级黄色大片| 国产美女娇喘av呻吟久久| avove在线播放| 亚洲国产成人av好男人在线观看| 免费成人蒂法网站| 久久久精品影视| 成人av免费在线观看| 欧美日韩一二三| 麻豆国产精品一区二区三区| 中文字幕观看av| 亚洲综合一区二区三区| 四虎永久免费在线观看| 国产精品久久久久aaaa| 亚洲一区二区三区四区av| 精品久久久久久久久久久久久久久久久 | 欧美一区国产二区| 极品销魂美女一区二区三区| 综合五月激情网| 一区二区三区电影在线播| 久久精品综合视频| 国产精品国产三级国产aⅴ无密码| av不卡中文字幕| 久久精品视频一区二区三区| 97久久人人超碰| 欧美不卡一区二区三区四区| 成人污视频在线观看| 欧美精品日日鲁夜夜添| 国产在线视视频有精品| 欧洲一区二区三区免费视频| 久久精品国产99| 在线视频一区二区三| 麻豆91在线观看| 在线免费观看视频一区| 久久99国产精品久久99| 日本丰满少妇一区二区三区| 蜜臀精品一区二区三区在线观看| wwwav国产| 久久精品99久久久| 欧美在线看片a免费观看| 精品一区二区国语对白| 欧美丝袜丝交足nylons图片| 国产一区二区三区在线观看精品| 欧美日韩色一区| 国产馆精品极品| 日韩久久精品一区| 无码人妻少妇色欲av一区二区| 337p粉嫩大胆噜噜噜噜噜91av| 99re6这里只有精品视频在线观看 99re8在线精品视频免费播放 | 2欧美一区二区三区在线观看视频 337p粉嫩大胆噜噜噜噜噜91av | 色婷婷一区二区三区四区| 久久电影网电视剧免费观看| 在线国产电影不卡| 国产精品亚洲一区二区三区妖精 | 94-欧美-setu| 国产日韩亚洲欧美综合| 加勒比精品视频| 亚洲美女屁股眼交3| 久久精品色妇熟妇丰满人妻| 天堂精品中文字幕在线| 91久久香蕉国产日韩欧美9色| 狠狠色狠狠色合久久伊人| 91麻豆精品国产91久久久久久| 成人av先锋影音| 国产日本欧洲亚洲| 在线国产视频一区| 日韩成人免费看| 欧美日韩午夜影院| 99re在线精品| 最新日韩av在线| 久久久久久久麻豆| 国产伦精品一区二区三区视频青涩 | 日韩av成人网| 亚洲免费在线视频| 国产精品丝袜一区二区| 国产一区二区美女诱惑| 精品福利视频一区二区三区| a级在线观看视频| 视频一区欧美日韩| 欧美另类高清zo欧美| 久草福利在线观看| 亚洲欧美一区二区不卡| 亚洲国产123| 国产另类ts人妖一区二区| 亚洲精品一区二区三区蜜桃下载 | 国产精品亚洲成人| 久久亚洲一区二区三区明星换脸| 麻豆精品免费视频| 青青草精品视频| 精品乱人伦一区二区三区| 在线 丝袜 欧美 日韩 制服| 日本欧美肥老太交大片| 欧美一区二区三区不卡| 亚洲久久久久久| 日本视频中文字幕一区二区三区| 91精品啪在线观看国产60岁| 国产精品久久久久久亚洲av| 婷婷开心激情综合| 日韩欧美国产一区在线观看| 久久久久久九九九九九| 麻豆一区二区在线| 久久综合色综合88| 日本综合在线观看| 国产精品综合二区| 国产精品久久看| 色妹子一区二区| 古装做爰无遮挡三级聊斋艳谭| 一区二区日韩av| 在线电影国产精品| 亚洲专区区免费| 国产一区二区伦理片| 亚洲国产成人一区二区三区| 2025国产精品自拍| 91人妻一区二区三区| 亚洲自拍偷拍图区| 欧美一区二区成人6969| 黑人巨大精品欧美| 国产精品一区二区三区99| 专区另类欧美日韩| 欧美天堂一区二区三区| 中文字幕影片免费在线观看| 狠狠狠色丁香婷婷综合激情| 国产精品久久精品日日| 欧美午夜片在线观看| 800av在线播放| 国产精品一区二区黑丝| ...中文天堂在线一区| 欧美日韩电影在线| 蜜桃传媒一区二区亚洲| 粉嫩av一区二区三区在线播放| 亚洲三级在线看| 91精品国产黑色紧身裤美女| 人成免费在线视频| 91视视频在线观看入口直接观看www | 日韩精品一区二区三区在线播放| 天天操天天舔天天射| 成人av网站在线| 天堂成人国产精品一区| 久久久久久久久久久久电影| 91久久精品一区二区三区| 性久久久久久久久久久| 国产精品一区二区久久不卡| 亚洲在线视频一区| 久久嫩草精品久久久久| 91官网在线免费观看| 中文字幕在线看高清电影| 不卡电影一区二区三区| 日韩成人av影视| 亚洲素人一区二区| 欧美成人精品福利| 色妞www精品视频| 欧美 日韩 国产 成人 在线观看| 99久久精品久久久久久清纯| 蜜臀精品久久久久久蜜臀 | 在线不卡的av| 性生交大片免费全黄| 国产精品九九视频| 成人午夜激情在线| 捆绑调教美女网站视频一区| 亚洲精品乱码久久久久久| 久久久高清一区二区三区| 欧美日韩一区国产| 国产黄色小视频网站| 亚洲最大的黄色网| 原创真实夫妻啪啪av| 国产一区二区三区在线观看免费视频 | 国产精品99精品久久免费| 亚洲成人tv网|