需要关于存储复杂数据库模式的建议 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: ""}, 
                      ...] 
         }, 
         ...]
},
...]

从上面看,集合本身就是一个对象数组。每个对象都有四个嵌套的值数组,即键 creditsgenresseasonsepisodes.

每次都需要读取完整的对象,因为需要在前端显示所有字段。

episodes键中的项目将被插入或删除最多。
他们被分组,分成季节,这也是一个数组

初始 sql table 模式是每集一行,但这会造成很多 json 冗余

查询returns上述对象的原始结构

很重要

从您写的内容来看,您似乎希望经常更新其中的某些部分 JSON。在这种情况下,如果您想使用 PostgreSQL,我只能建议 不要 将数据存储为 JSON,而是将其拆分为多个表:creditsgenresseasonsepisodes.

当然,这会使数据的 INSERTSELECT 变得更加复杂,因为您将不得不拆分 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 行。