Как создать Restful API ExpressJS с UUID и библиотекой Postgres pg-promise

Я пытаюсь создать CRUD для пользователя в своем веб-приложении. Я использую uuid для своего идентификатора (также первичный ключ, как показано в таблице пользователей ниже). Я использую библиотеку pg-promise для подключения к Postgres. Код маршрута для создания пользователей и получения работы всех пользователей. Но у меня возникла проблема с тем, как ссылаться на uuid при создании id const для получения одного пользователя, удаления пользователя или обновления пользователя, т.е. const user_id = parseInt(req.params.id);

Пожалуйста, смотрите мои примеры кодов ниже. Я также буду признателен за любой онлайн-ресурс с примером.

МОЯ ПОЛЬЗОВАТЕЛЬСКАЯ ТАБЛИЦА

CREATE TABLE m_user (
id uuid DEFAULT uuid_generate_v4() NOT NULL,
username text NOT NULL UNIQUE,
password text NOT NULL,
confirm_password text NOT NULL,
created_at timestamp NOT NULL default now(),
last_login timestamp NOT NULL default now(),
PRIMARY KEY (id)
);

CRUD ДЛЯ ПОЛУЧЕНИЯ ОДНОГО ПОЛЬЗОВАТЕЛЯ

function getSingleUser(req, res, next) {
  const showoneuserquery = 'SELECT * FROM user where id = $1'
  const user_id = parseInt(req.params.id);
  db.one(showoneuserquery, user_id)
    .then(function (data) {
      res.status(200)
        .json({
          status: 'success',
          data: data,
          message: 'Retrieved ONE user'
        });
    })

    .catch(function (err) {
      return next(err);
    });
}

CRUD ДЛЯ ИЗМЕНЕНИЯ ПОЛЬЗОВАТЕЛЯ

function editUser(req, res, next) {
  const edituserquery = 'update user set username=$1, password=$2, confirm_password=$3  where id=$4'
  db.none(edituserquery, [req.body.username, req.body.password, req.body.confirm_password, (req.params.id)])
    .then(function () {
      res.status(200)
        .json({
          status: 'success',
          message: 'Updated user'
        });
    })
    .catch(function (err) {
      return next(err);
    });
}

person Jetro Olowole    schedule 14.12.2019    source источник
comment
Можете ли вы включить код для вашего экспресс-маршрутизатора?   -  person Khauri    schedule 14.12.2019
comment
@Khauri Я отделяю бизнес-логику маршрутизатора от маршрута в файле контроллера. Коды, над которыми я работаю, - это бизнес-логика, как указано в моем вопросе. Но, возможно, я не понимаю код, на который вы ссылаетесь.   -  person Jetro Olowole    schedule 14.12.2019
comment
Пожалуйста, обновите свой вопрос с ошибками/ситуациями, с которыми вы сталкиваетесь после выполнения названных действий.   -  person    schedule 14.12.2019
comment
Вы сказали, что у вас проблемы со ссылкой на идентификатор с помощью req.params.id? Обычно вы указываете это значение в своем маршрутизаторе так: router.get('/:id', getSingleUser). Если это не то, что вы имели в виду, можете ли вы более конкретно рассказать об ошибке, которую вы получаете?   -  person Khauri    schedule 14.12.2019
comment
@Khauri Я правильно установил маршрут через router.get('/:id', getSingleUser). Часть, с которой я смущаюсь, - это место, где я объявляю константу для user_id const user_id = parseInt(req.params.id); Поскольку я использую uuid, я думаю, что мне следует использовать что-то другое, кроме функции parseInt.   -  person Jetro Olowole    schedule 14.12.2019
comment
Пара замечаний. Сначала отказ от ответственности, я не знаю ExpressJS. Но... Вы утверждаете, что используете uuid для основной таблицы. Однако это не так, как это определено на уровне таблицы базы данных. Опубликованная вами таблица DDL определяет идентификатор как BIGSERIAL. Это определение делает его 64-битным целым числом. Однако uuid представляет собой 32-байтовое шестнадцатеричное значение. Кроме того, пользователь соответствует стандарту Postgres и SQL зарезервированное слово. Пока вам может сойти с рук его использование, которое может исчезнуть, если команда разработчиков Postgres решит ближе придерживаться стандарта SQL.   -  person Belayer    schedule 15.12.2019
comment
Belayer опередил меня на секунду ... Действительно, в вопросе есть противоречие: поиск информации об использовании UUID, показывая использование 64-битного целого числа в таблице (BIGSERIAL). UUID — это просто строки, и они используются как таковые везде, в то время как 64-битные целые числа имеют некоторые особенности, например объяснено здесь.   -  person vitaly-t    schedule 15.12.2019
comment
@Belayer идентификатор был исправлен на uuid. Это была ошибка, но мой вопрос все еще остается. Кроме того, я добавляю префикс к имени пользовательской таблицы в своем проекте.   -  person Jetro Olowole    schedule 15.12.2019


Ответы (1)


Хорошо, пара замечаний по UUID. @vitaly_t не совсем правильный uuid - это не просто строки. Хотя визуально они выглядят как строки, и вы можете обрабатывать их как строки, они хорошо UUID. Имея строки с уникальными свойствами, наиболее заметно, что они имеют несколько представлений форматов. Ниже небольшая демонстрация, показывающая это. Строка не может сделать это функционально.

create table uuid_demo(uuid_col uuid,  description text);

-- insert a generated systen function generated uuid
-- requires pgcrypto extension
insert into uuid_demo(uuid_col, description)
     values (gen_random_uuid(),'Systen Generated uuid') ;

-- show generated
select * from uuid_demo;
/*
uuid_col                            ;description
d41c9d09-0e21-4acf-b82c-41f009c84aeb;Systen Generated uuid
*/

-- query demo with generated uuid, both with and without formatting
select uuid_demo.*,'#1. Standard Form'  note       from uuid_demo where uuid_col = 'd41c9d09-0e21-4acf-b82c-41f009c84aeb'
union all
select uuid_demo.*,'#2. Standard, cast'            from uuid_demo where uuid_col = 'd41c9d09-0e21-4acf-b82c-41f009c84aeb'::uuid
union all
select uuid_demo.*,'#3 Non Standard Upper case'    from uuid_demo where uuid_col = 'D41C9D09-0E21-4ACF-B82C-41F009C84AEB'
union all
select uuid_demo.*,'#4 Non Standard Unformatted'   from uuid_demo where uuid_col = 'd41c9d090e214acfb82c41f009c84aeb'
union all
select uuid_demo.*,'#5 Non Std. Upper Unformatted' from uuid_demo where uuid_col = 'D41C9D090E214ACFB82C41F009C84AEB'
union all
select uuid_demo.*,'#7 Non Standard bracket'       from uuid_demo where uuid_col = '{d41c9d090e214acfb82c41f009c84aeb}';

/*
uuid_col                            ;description          ;note
d41c9d09-0e21-4acf-b82c-41f009c84aeb;Systen Generated uuid;#1. Standard Form
d41c9d09-0e21-4acf-b82c-41f009c84aeb;Systen Generated uuid;#2. Standard, cast
d41c9d09-0e21-4acf-b82c-41f009c84aeb;Systen Generated uuid;#3. Non Standard Upper case
d41c9d09-0e21-4acf-b82c-41f009c84aeb;Systen Generated uuid;#4. Non Standard Unformatted
d41c9d09-0e21-4acf-b82c-41f009c84aeb;Systen Generated uuid;#5. Non Std. Upper Unformatted
d41c9d09-0e21-4acf-b82c-41f009c84aeb;Systen Generated uuid;#6. Non Standard bracket

Теперь о вашей прямой проблеме: как вы должны на это ссылаться. Здесь vitaly_t прав в том, что в вашем коде просто обработайте его как строку.

  1. Попробуйте Стандарт для (#1). Это форма, которую Postgres всегда будет предоставлять в качестве вывода.
  2. Попробуйте использовать оператор приведения Postgres (::) (#2).
  3. Попробуйте директиву Postgres CAST (не показана выше).

Я попробую поместить каждый из них в формат ExpressJS. Но я не даю никаких гарантий (я просто скопировал и изменил ваш пост). Снова см. мой предыдущий отказ от ответственности.

  1. const showoneuserquery = 'SELECT * FROM пользователя, где id = $1'
  2. const showoneuserquery = 'SELECT * FROM пользователя, где id = $1::uuid'
  3. const showoneuserquery = 'SELECT * FROM user where id = CAST ($1 как UUID)'

Для операций обновления и удаления используется тот же формат.

Если ничего из этого не работает, у вас есть другой вариант. Поскольку у вас есть уникальное ограничение на имя пользователя, просто используйте его для доступа к таблице пользователей, а затем просто используйте UUID при присоединении к таблице пользователей, которая должна быть именем столбца UUID для имени столбца UUID. Ничего особенного не нужно.

person Belayer    schedule 15.12.2019
comment
Спасибо @Belayer, я протестировал использование имени пользователя, и оно работает до того, как пришел ваш ответ. Я последую вашему предложению и буду использовать uuid при присоединении к таблице. У меня также есть некоторые аспекты приложения, где я все еще буду использовать uuid. - person Jetro Olowole; 15.12.2019