POSTGRESQL Вставить несколько строк из данного массива JSON, использовать результаты вставки для других вставок - PullRequest
0 голосов
/ 27 сентября 2019

TL; DR Приложение Music Streaming - позволяет пользователям загружать свои собственные файлы.Файлы будут сохранены в FileSet.Я хочу передать более одного FILE (массива fileRecords) с одним FILESET и вставить в соответствующие таблицы.

Извините, если это немного сбивает с толку - в основном я работаю с 3 таблицами:

Таблица файлов

CREATE TABLE file
(
    -- Most tables should have a table_id & table_cuid
    file_id         BIGSERIAL   NOT NULL ,
    file_cuid       VARCHAR     NOT NULL,

    -- This section is specific to this table
    user_id         BIGINT      NOT NULL,

    -- File fields
    filename        VARCHAR     NOT NULL,
    last_modified   TIMESTAMP WITHOUT TIME ZONE NOT NULL,
    size_in_bytes   VARCHAR     NOT NULL,
    mime_type       VARCHAR     NOT NULL,

    -- Most tables should also have timestamps
    created_timestamp  TIMESTAMP WITHOUT TIME ZONE  NOT NULL,
    updated_timestamp  TIMESTAMP WITHOUT TIME ZONE  NOT NULL,

    -- Constraints
    PRIMARY KEY (file_id),
    FOREIGN KEY (user_id)   REFERENCES users (user_id),
    CONSTRAINT file_cuid_unique  UNIQUE     (file_cuid)
)

Таблица наборов файлов

CREATE TABLE fileset
(
    -- Most tables should have a table_id & table_cuid
    fileset_id         BIGSERIAL   NOT NULL ,
    fileset_cuid       VARCHAR     NOT NULL,

    user_id         BIGINT      NOT NULL,

    -- Fileset fields TBD

    created_timestamp  TIMESTAMP WITHOUT TIME ZONE  NOT NULL,
    updated_timestamp  TIMESTAMP WITHOUT TIME ZONE  NOT NULL,

    -- Constraints
    PRIMARY KEY (fileset_id),
    FOREIGN KEY (user_id)   REFERENCES users (user_id),
    CONSTRAINT cuid_unique_fileset  UNIQUE     (fileset_cuid)
)

и, наконец, Таблица File_FileSet_Rel

CREATE TABLE file_fileset_rel
(
    file_id         BIGSERIAL   NOT NULL,
    fileset_id      BIGSERIAL   NOT NULL,

    FOREIGN KEY (file_id)  REFERENCES file   (file_id),
    FOREIGN KEY (fileset_id)   REFERENCES fileset (fileset_id),
    UNIQUE      (file_id, fileset_id)
)

С каждой песней будет связан один FileSet, а с этим набором файлов будет связан один / несколько файлов.

Функция ниже (file_upload_process) позволяет мне добавить файл в таблицу (возвращая file_id ), а также добавляя набор файлов в таблицу (возвращая fileset_id ), и, наконец, функция вставляет оба этих значения в окончательную таблицу file_fileset_rel

file_upload_process.sql

CREATE OR REPLACE FUNCTION file_upload_process(
  _file_cuid VARCHAR,
  _fileset_cuid VARCHAR,
  _cognito_id VARCHAR,
  _name VARCHAR,
  _last_modified TIMESTAMP,
  _size DECIMAL,
  _type VARCHAR
)
RETURNS TABLE(
  fileId BIGINT,
  fileSetID BIGINT
)
AS $file_upload_process$
DECLARE
v_user_id BIGINT;
v_file_id BIGINT;
v_fileset_id BIGINT;
BEGIN

-- Create Song/ Update song
  -- store user_id
  v_user_id := (
    SELECT * FROM get_user_id(_cognito_id)
  );

  -- --Insert In FILE table
  v_file_id := (
    SELECT *
    FROM create_file(
    _file_cuid,
    v_user_id,
    _name,
    _last_modified,
    _size,
    _type
    )
  );

  --Insert into fileset table
  v_fileset_id := (
  SELECT * FROM create_fileset(_fileset_cuid, v_user_id)
  );

  RETURN QUERY
  INSERT INTO file_fileset_rel(file_id, fileset_id)
  VALUES (
    v_file_id,
    v_fileset_id
  )
  RETURNING file_fileset_rel.file_id,
            file_fileset_rel.fileset_id;
END;
$file_upload_process$ LANGUAGE PLPGSQL;

, который вызывает следующие функции внутри:

create_file.sql

CREATE OR REPLACE FUNCTION create_file(
  _file_cuid VARCHAR,
  _user_id BIGINT,
  _name VARCHAR,
  _last_modified TIMESTAMP,
  _size DECIMAL,
  _type VARCHAR
)
RETURNS TABLE (
  _file_id BIGINT
)
AS $create_file$
BEGIN
  RETURN QUERY
-- Create Song/ Update song
  INSERT INTO file(
    file_cuid,
    user_id,
    filename,
    last_modified,
    size_in_bytes,
    mime_type,
    created_timestamp,
    updated_timestamp
  )
  VALUES(
    _file_cuid,
    _user_id,
    _name,
    _last_modified,
    _size,
    _type,
    now(),
    now()
  )
  RETURNING "file".file_id;
END;
$create_file$ LANGUAGE PLPGSQL;

И функция create_fileset:

    CREATE OR REPLACE FUNCTION create_fileset(
  _fileset_cuid VARCHAR,
  _user_id BIGINT
)
RETURNS TABLE (
  _fileset_id BIGINT
)
AS $create_fileset$
BEGIN
-- Create Song/ Update song
  RETURN QUERY
  INSERT INTO fileset(
    fileset_cuid,
    user_id,
    created_timestamp,
    updated_timestamp
  )
  VALUES(
    _fileset_cuid,
    _user_id,
    now(),
    now()
  )
  RETURNING "fileset".fileset_id;
END;
$create_fileset$ LANGUAGE PLPGSQL;

Проблема, с которой я столкнулся, заключается в том, что эта функция позволяет добавлять только 1 файл за раз, пользователи могут загружать 5-10 файлов для 1 песни (1 набор файлов), поэтому мне нужен способ циклического просмотрамассив fileRecords и сохраните значения этих полей в столбцах таблицы FILE - наконец, я могу добавить несколько записей в таблицу file_fileset_rel.

Если у кого-то есть более простые способы сделать все это или, что более важно, решениев MANY vs Одна вставка была бы огромной помощью.

EDIT: Пример CURRENT тела, отправляемого в lambda - перед передачей в URL функции postgresql -> fileset / {filesetCuid} / file

body: {
"cognitoId" : "9dc766a0-c5c9-4455-932e-46c243c80266",
"fileRecord" : {
    "fileCuid" : "someotherfilecuid23",
    "name" : "file_name",
    "last_modified" : "06/03/1995",
    "size" : 530,
    "type" : "mp3/audio"
}
}

Конечная цель - отправить несколько файлов: URL -> набор файлов / {filesetCuid} / file

body: {
"cognitoId" : "9dc766a0-c5c9-4455-932e-46c243c80266",
"fileRecords" : [{
    "fileCuid" : "someotherfilecuid23",
    "name" : "file_name",
    "last_modified" : "06/03/1995",
    "size" : 530,
    "type" : "mp3/audio"
}, {...}, {...}]
}
...