【问题标题】:Database schema with ManyToMany self-referencing relation具有多对多自引用关系的数据库模式
【发布时间】:2015-07-24 10:10:12
【问题描述】:

我正在设计 MySQL 数据库架构,但我不确定我的方法是否足够好。

想象一下这种情况:

  • 有些人
  • 每个人都喜欢互联网上的一些文章(数千篇文章)
  • 每篇文章都被翻译成另一种语言(数十种语言,在不同的网站上可能会有不同的翻译)

我希望能够指定文章的名称、源语言、目标语言并找到这篇文章的所有翻译。我也可以指定一个人,只从他/她的“收藏夹”中查找文章。

我的想法:

创建 4 个表:

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;

将每篇文章作为记录存储在表中,并使用链接表Relation“连接”它们。

每个人都将创建一个文件,其中包含他/她最喜欢的文章的 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_deurl_1_de_2

这里的问题是如何处理文章的这种自引用多对多关系。表关系也将增长得非常快。

也许有更好的方法来设计架构?

【问题讨论】:

    标签: mysql database-schema


    【解决方案1】:

    一般来说,您的方法是可以的。不过,我发现了一个错误。文章不应该与人绑定 - 如果两个人喜欢同一篇文章怎么办?

    此外,由于人们可能喜欢一篇文章(而不是其翻译),您可以再增加一层复杂性。文章只是一个没有内容的容器,内容在ArticleTranslation表中

    我提出的架构如下(我只关注表关系):

    Article
      *..* Person [with join table PersonArticle]
      1..* ArticleContent
    
    Person
       *..* Article [with join table PersonArticle]
    

    然后,您的查询将如下(再次 - 伪代码):

    查找翻译

    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>
    

    查找用户最爱的翻译

    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>
    

    更新 - 对于大量数据,您可以考虑使用一些 NoSQL 方法。其中一些是专门为映射此类数据图而创建的。然而,这是更复杂的解决方案,SQL 适合初学者。

    【讨论】:

      猜你喜欢
      • 2018-06-09
      • 1970-01-01
      • 2023-03-23
      • 2010-12-08
      • 1970-01-01
      • 2011-05-03
      • 1970-01-01
      • 1970-01-01
      • 2019-08-31
      相关资源
      最近更新 更多