具有多对多自引用关系的数据库模式
Database schema with ManyToMany self-referencing relation
我正在设计 MySQL 数据库架构,我不确定我的方法是否足够好。
想象一下这种情况:
- 有人
- 每个人都喜欢互联网上的一些文章(数千篇)
- 每篇文章都翻译成另一种语言(数十种语言,在不同的网站上可以有不同的翻译)
我希望能够指定文章名称、源语言、目标语言并找到这篇文章的所有翻译。我也可以指定一个人,只查找来自 his/her "favorites".
的文章
我的想法:
创建 4 tables:
CREATE TABLE Language (
`id` INT NOT NULL AUTO_INCREMENT,
`name` VARCHAR(30) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB;
CREATE TABLE Person (
`id` INT NOT NULL AUTO_INCREMENT,
`name` VARCHAR(50) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB;
CREATE TABLE Article (
`id` INT NOT NULL AUTO_INCREMENT,
`name` VARCHAR(100) NOT NULL,
`language` INT NOT NULL,
`person` INT NOT NULL,
PRIMARY KEY (`id`),
FOREIGN KEY (`language`) REFERENCES Language (`id`),
FOREIGN KEY (`person`) REFERENCES Person (`id`)
) ENGINE=InnoDB;
CREATE TABLE Relation (
`article_1` INT NOT NULL,
`article_2` INT NOT NULL,
PRIMARY KEY (`article_1`, `article_2`),
FOREIGN KEY (`article_1`) REFERENCES Article (`id`) ON DELETE CASCADE,
FOREIGN KEY (`article_2`) REFERENCES Article (`id`) ON DELETE CASCADE
) ENGINE=InnoDB;
使用 link table Relation
.
将每篇文章作为记录存储在 table 和 "connect" 中
每个人都将创建一个文件,其中包含 his/her 最喜欢的文章的 URL 和 link 翻译的 URL:
url1_en url1_es url1_de url1_ko
url2_en url2_es url2_de url2_ko
url3_en url3_es url3_de url3_ko
url4_en url4_es url4_de url4_ko
当然,其他人可以为文章url1_en
找到另一个德语翻译并上传:
url1_en url1_es url1_de_2 url1_ko
如果我以德语作为目标语言搜索 url1_en
,我应该得到 url1_de
和 url_1_de_2
我这里的问题是如何处理文章的这种自引用多对多关系。此外 table 关系将发展得非常快。
也许有更好的模式设计方法?
总的来说,你的方法是可以的。不过,我发现了一个错误。文章不应与人绑定 - 如果两个人都喜欢同一篇文章怎么办?
此外,由于人们可能喜欢一篇文章(而不是其翻译),您可以再增加一个复杂程度。 Article只是一个没有内容的容器,内容在ArticleTranslationtable
我提议的模式如下(我只关注 table 关系):
Article
*..* Person [with join table PersonArticle]
1..* ArticleContent
Person
*..* Article [with join table PersonArticle]
然后,您的查询将如下(再次 - 伪代码):
Find translations
SELECT ac2.* FROM Article a
JOIN ArticleContent ac1
JOIN ArticleContent ac2 (ac1.Article=ac2.Article)
WHERE ac1.name=<NAME>
AND ac1.language=<SRC_LANG>
AND ac2.language=<TRG_LANG>
Find translations of user favorites
SELECT ac2.*
FROM
Person p
JOIN PersonArticle pa
JOIN Article a
JOIN ArticleContent ac1
JOIN ArticleContent ac2 (ac1.Article=ac2.Article)
WHERE
p.id=<PERSON_ID>
ac1.name=<NAME>
AND ac1.language=<SRC_LANG>
AND ac2.language=<TRG_LANG>
UPDATE - 对于非常大量的数据,您可以考虑使用一些 NoSQL 方法。其中一些是专门为映射此类数据图而创建的。然而,这是更复杂的解决方案,SQL 适合初学者。
我正在设计 MySQL 数据库架构,我不确定我的方法是否足够好。
想象一下这种情况:
- 有人
- 每个人都喜欢互联网上的一些文章(数千篇)
- 每篇文章都翻译成另一种语言(数十种语言,在不同的网站上可以有不同的翻译)
我希望能够指定文章名称、源语言、目标语言并找到这篇文章的所有翻译。我也可以指定一个人,只查找来自 his/her "favorites".
的文章我的想法:
创建 4 tables:
CREATE TABLE Language (
`id` INT NOT NULL AUTO_INCREMENT,
`name` VARCHAR(30) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB;
CREATE TABLE Person (
`id` INT NOT NULL AUTO_INCREMENT,
`name` VARCHAR(50) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB;
CREATE TABLE Article (
`id` INT NOT NULL AUTO_INCREMENT,
`name` VARCHAR(100) NOT NULL,
`language` INT NOT NULL,
`person` INT NOT NULL,
PRIMARY KEY (`id`),
FOREIGN KEY (`language`) REFERENCES Language (`id`),
FOREIGN KEY (`person`) REFERENCES Person (`id`)
) ENGINE=InnoDB;
CREATE TABLE Relation (
`article_1` INT NOT NULL,
`article_2` INT NOT NULL,
PRIMARY KEY (`article_1`, `article_2`),
FOREIGN KEY (`article_1`) REFERENCES Article (`id`) ON DELETE CASCADE,
FOREIGN KEY (`article_2`) REFERENCES Article (`id`) ON DELETE CASCADE
) ENGINE=InnoDB;
使用 link table Relation
.
每个人都将创建一个文件,其中包含 his/her 最喜欢的文章的 URL 和 link 翻译的 URL:
url1_en url1_es url1_de url1_ko
url2_en url2_es url2_de url2_ko
url3_en url3_es url3_de url3_ko
url4_en url4_es url4_de url4_ko
当然,其他人可以为文章url1_en
找到另一个德语翻译并上传:
url1_en url1_es url1_de_2 url1_ko
如果我以德语作为目标语言搜索 url1_en
,我应该得到 url1_de
和 url_1_de_2
我这里的问题是如何处理文章的这种自引用多对多关系。此外 table 关系将发展得非常快。
也许有更好的模式设计方法?
总的来说,你的方法是可以的。不过,我发现了一个错误。文章不应与人绑定 - 如果两个人都喜欢同一篇文章怎么办?
此外,由于人们可能喜欢一篇文章(而不是其翻译),您可以再增加一个复杂程度。 Article只是一个没有内容的容器,内容在ArticleTranslationtable
我提议的模式如下(我只关注 table 关系):
Article
*..* Person [with join table PersonArticle]
1..* ArticleContent
Person
*..* Article [with join table PersonArticle]
然后,您的查询将如下(再次 - 伪代码):
Find translations
SELECT ac2.* FROM Article a
JOIN ArticleContent ac1
JOIN ArticleContent ac2 (ac1.Article=ac2.Article)
WHERE ac1.name=<NAME>
AND ac1.language=<SRC_LANG>
AND ac2.language=<TRG_LANG>
Find translations of user favorites
SELECT ac2.*
FROM
Person p
JOIN PersonArticle pa
JOIN Article a
JOIN ArticleContent ac1
JOIN ArticleContent ac2 (ac1.Article=ac2.Article)
WHERE
p.id=<PERSON_ID>
ac1.name=<NAME>
AND ac1.language=<SRC_LANG>
AND ac2.language=<TRG_LANG>
UPDATE - 对于非常大量的数据,您可以考虑使用一些 NoSQL 方法。其中一些是专门为映射此类数据图而创建的。然而,这是更复杂的解决方案,SQL 适合初学者。