如何在postgres中建模一个包含对象的数组,每个对象都有一个String for title和一个子数组的字符串

时间:2016-06-08 21:58:36

标签: node.js postgresql postgresql-9.3 postgresql-9.2 postgresql-9.4

我在json中存储了以下格式来存储律师,我怀疑如何在postgres中建模“特色”字段,其中包含一个对象数组,每个对象都有一个标题和子专业的子数组:

{
  "id": 1,
  "name": "John Johnson Johannes",
  "gender": "f",
  "specialties": [
    {
      "specialty": "Business law",
      "sub-specialties": [
        "Incorporation",
        "Taxes",
        "Fusions"
      ]
    },
        {
      "specialty": "Criminal law",
      "sub-specialties": [
        "Property offenses",
        "Personal offenses",
        "Strict liability"
      ]
    }
  ]
}

我在Postgres做了这个律师表:

DROP DATABASE IF EXISTS lawyers_db;
CREATE DATABASE lawyers_db;

\c lawyers_db;

CREATE TYPE gen AS ENUM ('f', 'm');

CREATE TABLE lawyers_tb (
  ID SERIAL PRIMARY KEY,
  name VARCHAR,
  gender gen
);

INSERT INTO lawyers_tb (name, gender)
  VALUES ('John Doe', 'm');

我正在使用一些node.js库,当我从Postgres表读取数据时,它将数据作为JSON返回,因此我想保留关系模型,而不使用JSONb作为文档存储我的律师。

是否有可能在不使用JSONb类型的情况下实现我想要的目标?

1 个答案:

答案 0 :(得分:0)

暂时忘掉对象并真正思考数据是什么以及它们之间的关系(我们毕竟使用关系数据库)。

你在这里只是一种关系。

你有律师,你有专业。这种关系是律师拥有专业和专业属于律师(n-to-n关系),专业与专业(n-to-n)之间的关系也是如此。

首先,让我们做一个简单的1对n关系结构:

id

这有效,但会产生重复,因为每个专业只能属于一名律师,因此,如果两位律师专注于“商业法”和#34;你必须定义"商业法"两次。更糟糕的是,对于每个专业,您还必须复制子专业。

解决方案是连接表(也称为映射/映射表):

CREATE TABLE lawyers_tb (
  ID SERIAL PRIMARY KEY,
  name VARCHAR,
  gender gen
);

CREATE TABLE specialties_tb (
  ID SERIAL PRIMARY KEY,
  name VARCHAR,
  lawyer_ID INTEGER
);

CREATE TABLE subspecialties_tb (
  ID SERIAL PRIMARY KEY,
  name VARCHAR,
  specialty_ID INTEGER
);

这样每个专业都可以属于不止一个律师(真正的n对n关系),每个专业都可以属于不止一个专业。

您可以使用联接来获取整个数据集:

CREATE TABLE lawyers_tb (
  ID SERIAL PRIMARY KEY,
  name VARCHAR,
  gender gen
);

CREATE TABLE lawyer_specialties_tb (
  name VARCHAR,
  lawyer_ID INTEGER,
  specialty_ID INTEGER
);

CREATE TABLE specialties_tb (
  ID SERIAL PRIMARY KEY,
  name VARCHAR
);

CREATE TABLE specialty_subspecialties_tb (
  name VARCHAR,
  specialty_ID INTEGER,
  subspecialty_ID INTEGER
);

CREATE TABLE subspecialties_tb (
  ID SERIAL PRIMARY KEY,
  name VARCHAR
);

是的,查询起来有点复杂,但结构允许您单独维护每个数据集并定义它们之间的正确关系。

您可能还希望将连接表中的键定义为外键,以强制执行数据集的正确性。