需要关于存储复杂数据库模式的建议 json
Need advice on database schema for storing complex json
我无法决定是使用 postgres、cassandra 还是其他的 sql
json合集是这样的
[{
id:
name:
year:
credits: [{id: "", name: "", role: ""}...]
genres: [{id: "", name: ""}...]
seasons: [
{ id:
name:
season_number:
episodes: [
{id: "",
name: "",
season_number: "",
episode_number: ""},
...]
},
...]
},
...]
从上面看,集合本身就是一个对象数组。每个对象都有四个嵌套的值数组,即键 credits
、genres
、seasons
、episodes
.
每次都需要读取完整的对象,因为需要在前端显示所有字段。
episodes
键中的项目将被插入或删除最多。
他们被分组,分成季节,这也是一个数组
初始 sql table 模式是每集一行,但这会造成很多 json 冗余
查询returns上述对象的原始结构
很重要
从您写的内容来看,您似乎希望经常更新其中的某些部分 JSON。在这种情况下,如果您想使用 PostgreSQL,我只能建议 不要 将数据存储为 JSON,而是将其拆分为多个表:credits
、genres
、seasons
和 episodes
.
当然,这会使数据的 INSERT
和 SELECT
变得更加复杂,因为您将不得不拆分 assemble 和 JSON,但是一旦您尝试执行诸如“删除特定剧集”之类的请求,或者您想使用模式匹配有效地搜索数据,它就会得到回报。
此外,如果您需要保留 JSON 中的空格或属性顺序,这将无法按预期工作。但这对于 JSON 数据应该无关紧要。
我同意 Laurenz 的回答,即 PostgreSQL 是更好的选择,因为 update/deletes。您可以将数据存储在标准 SQL 表中,并使用 PostgreSQL JSON 支持生成必要的 JSON.
为了演示,我采用了您的示例并在 db_fiddle 中创建了一个工作示例,您可以在此处访问 https://www.db-fiddle.com/f/81Acp5wdEEaWMMxKfvbUaS/3。
create schema test;
create table test.tvshow ( id serial, name text );
create table test.credit ( id serial, show_id integer, name text , role text );
create table test.genre (id serial, name text, show_id integer );
create table test.season ( id serial, name text, season_number text, show_id integer);
create table test.episode ( id serial, name text, season_id integer, episode_number text, show_id integer);
insert into test.tvshow (name) values ('gunsmoke');
insert into test.credit (name, show_id) values ('credits #1', 1);
insert into test.credit (name, show_id) values ('credits #2', 1);
insert into test.credit (name, show_id) values ('credits #3', 1);
insert into test.genre (name, show_id) values ('western', 1);
insert into test.genre (name, show_id) values ('drama', 1);
insert into test.season (name, show_id, season_number) values ('Season 1', 1, '01');
insert into test.season (name, show_id, season_number) values ('Season 2', 1, '02');
insert into test.episode (name, season_id, episode_number, show_id) values ('Episode#1',1, '01', 1);
insert into test.episode (name, season_id, episode_number, show_id) values ('Episode#2',1, '01', 1);
insert into test.episode (name, season_id, episode_number, show_id) values ('Episode#3',1, '01', 1);
insert into test.episode (name, season_id, episode_number, show_id) values ('Episode#1',2, '01', 1);
insert into test.episode (name, season_id, episode_number, show_id) values ('Episode#1',2, '02', 1);
填充后,您可以执行以下操作 SQL。
SELECT array_to_json(array_agg(row_to_json(t, true)))
FROM (
SELECT name
,(
SELECT array_to_json(array_agg(row_to_json(c)))
FROM (
SELECT id
,name
,ROLE
FROM test.credit
WHERE test.credit.show_id = test.tvshow.id
) c
) AS credits
,
--
(
SELECT array_to_json(array_agg(row_to_json(g)))
FROM (
SELECT id
,name
FROM test.genre
WHERE test.genre.show_id = test.tvshow.id
) g
) AS genres
,
--
(
SELECT array_to_json(array_agg(row_to_json(s, true)))
FROM (
SELECT id
,name
,season_number
,(
SELECT array_to_json(array_agg(row_to_json(e)))
FROM (
SELECT id
,name
,season_number
FROM test.episode
WHERE test.episode.show_id = test.tvshow.id
AND test.episode.season_id = test.season.id
) e
) AS episodes
FROM test.season
WHERE test.season.show_id = test.tvshow.id
) s
) AS seasons
--
FROM test.tvshow
) t
这将 return 与所有节目的 JSON 行。
我无法决定是使用 postgres、cassandra 还是其他的 sql
json合集是这样的
[{
id:
name:
year:
credits: [{id: "", name: "", role: ""}...]
genres: [{id: "", name: ""}...]
seasons: [
{ id:
name:
season_number:
episodes: [
{id: "",
name: "",
season_number: "",
episode_number: ""},
...]
},
...]
},
...]
从上面看,集合本身就是一个对象数组。每个对象都有四个嵌套的值数组,即键 credits
、genres
、seasons
、episodes
.
每次都需要读取完整的对象,因为需要在前端显示所有字段。
episodes
键中的项目将被插入或删除最多。
他们被分组,分成季节,这也是一个数组
初始 sql table 模式是每集一行,但这会造成很多 json 冗余
查询returns上述对象的原始结构
很重要从您写的内容来看,您似乎希望经常更新其中的某些部分 JSON。在这种情况下,如果您想使用 PostgreSQL,我只能建议 不要 将数据存储为 JSON,而是将其拆分为多个表:credits
、genres
、seasons
和 episodes
.
当然,这会使数据的 INSERT
和 SELECT
变得更加复杂,因为您将不得不拆分 assemble 和 JSON,但是一旦您尝试执行诸如“删除特定剧集”之类的请求,或者您想使用模式匹配有效地搜索数据,它就会得到回报。
此外,如果您需要保留 JSON 中的空格或属性顺序,这将无法按预期工作。但这对于 JSON 数据应该无关紧要。
我同意 Laurenz 的回答,即 PostgreSQL 是更好的选择,因为 update/deletes。您可以将数据存储在标准 SQL 表中,并使用 PostgreSQL JSON 支持生成必要的 JSON.
为了演示,我采用了您的示例并在 db_fiddle 中创建了一个工作示例,您可以在此处访问 https://www.db-fiddle.com/f/81Acp5wdEEaWMMxKfvbUaS/3。
create schema test;
create table test.tvshow ( id serial, name text );
create table test.credit ( id serial, show_id integer, name text , role text );
create table test.genre (id serial, name text, show_id integer );
create table test.season ( id serial, name text, season_number text, show_id integer);
create table test.episode ( id serial, name text, season_id integer, episode_number text, show_id integer);
insert into test.tvshow (name) values ('gunsmoke');
insert into test.credit (name, show_id) values ('credits #1', 1);
insert into test.credit (name, show_id) values ('credits #2', 1);
insert into test.credit (name, show_id) values ('credits #3', 1);
insert into test.genre (name, show_id) values ('western', 1);
insert into test.genre (name, show_id) values ('drama', 1);
insert into test.season (name, show_id, season_number) values ('Season 1', 1, '01');
insert into test.season (name, show_id, season_number) values ('Season 2', 1, '02');
insert into test.episode (name, season_id, episode_number, show_id) values ('Episode#1',1, '01', 1);
insert into test.episode (name, season_id, episode_number, show_id) values ('Episode#2',1, '01', 1);
insert into test.episode (name, season_id, episode_number, show_id) values ('Episode#3',1, '01', 1);
insert into test.episode (name, season_id, episode_number, show_id) values ('Episode#1',2, '01', 1);
insert into test.episode (name, season_id, episode_number, show_id) values ('Episode#1',2, '02', 1);
填充后,您可以执行以下操作 SQL。
SELECT array_to_json(array_agg(row_to_json(t, true)))
FROM (
SELECT name
,(
SELECT array_to_json(array_agg(row_to_json(c)))
FROM (
SELECT id
,name
,ROLE
FROM test.credit
WHERE test.credit.show_id = test.tvshow.id
) c
) AS credits
,
--
(
SELECT array_to_json(array_agg(row_to_json(g)))
FROM (
SELECT id
,name
FROM test.genre
WHERE test.genre.show_id = test.tvshow.id
) g
) AS genres
,
--
(
SELECT array_to_json(array_agg(row_to_json(s, true)))
FROM (
SELECT id
,name
,season_number
,(
SELECT array_to_json(array_agg(row_to_json(e)))
FROM (
SELECT id
,name
,season_number
FROM test.episode
WHERE test.episode.show_id = test.tvshow.id
AND test.episode.season_id = test.season.id
) e
) AS episodes
FROM test.season
WHERE test.season.show_id = test.tvshow.id
) s
) AS seasons
--
FROM test.tvshow
) t
这将 return 与所有节目的 JSON 行。