Настройка базы данных PostgreSQL

Полезное#

Видео:

Вопросы, можно задать в комментариях телеграмма: TG: fitgame

Таблицы базы данных#

Структура users_social:

Структура users:

Ключи и индексы#

Ключи и индексы в users_social:

Ключи и индексы в users:

Создание профиля#

Хранимая процедура для создание профиля игрока

CREATE OR REPLACE FUNCTION create_user(in_social json, in_user json)
RETURNS integer AS $$
DECLARE _user_id integer;
        in_inventory JSON;
BEGIN

  INSERT INTO users_social (social_type, social_id) VALUES(in_social->>'type',in_social->>'social_id') RETURNING id INTO _user_id;
  INSERT INTO users(id, json_data, points) VALUES(_user_id, (in_user->>'json_data')::json, ((in_user->>'json_data')::json->>'points')::int);

RETURN _user_id;

END;
$$ LANGUAGE plpgsql;

Запрос

select create_user('{"type": "vk", "social_id": 1}', '{"json_data": {"name": "FITGAME", "gold": 100, "energy": 50, "points": 100}}');

Получение профиля#

Хранимая процедура для получения айди на основе типа площадки и айди площадки

CREATE OR REPLACE FUNCTION get_social_info(in_social JSONB)
RETURNS integer AS $$
DECLARE _user_id integer = 0;
BEGIN

  SELECT id INTO _user_id FROM users_social WHERE social_type = (in_social->>'type') AND social_id = (in_social->>'social_id');

  IF _user_id IS NULL THEN
    _user_id = 0;
  END IF;

  RETURN _user_id;

END;
$$ LANGUAGE plpgsql STABLE;

Запрос

select get_social_info('{"type":"vk", "social_id": "1"}');

Хранимая процедура для получения данных профиля на основе айди

CREATE OR REPLACE FUNCTION get_user_info(in_user_id integer)
RETURNS JSONB AS $$
DECLARE out_json JSONB = '{}';
BEGIN

  SELECT row_to_json(row) INTO out_json FROM (SELECT * FROM users WHERE id = in_user_id) row;

  IF out_json IS NULL THEN
    out_json = '{}';
  END IF;

  RETURN out_json;

END;
$$ LANGUAGE plpgsql STABLE;

Запрос

select get_user_info(1);

Хранимая процедура для получения всех данных профиля на основе типа площадки и айди площадки

CREATE OR REPLACE FUNCTION get_user_info_2 (in_social JSONB)
RETURNS JSONB AS $$
DECLARE out_json JSONB = '{}';
BEGIN

  SELECT row_to_json(row) INTO out_json FROM (SELECT * FROM users JOIN users_social ON users_social.id = users.id WHERE social_type = (in_social->>'type') AND social_id = (in_social->>'social_id')) row;

  IF out_json IS NULL THEN
    out_json = '{}';
  END IF;

  RETURN out_json;

END;
$$ LANGUAGE plpgsql STABLE;

Запрос

select get_user_info_2('{"type":"vk", "social_id": "1"}');

Обновление профиля#

Хранимая процедура для обновления профиля игрока

CREATE OR REPLACE FUNCTION update_user(in_user_id integer, in_user JSONB)
RETURNS boolean AS $$
BEGIN

  UPDATE users SET 
    json_data =  (in_user->>'json_data')::json, points =  ((in_user->>'json_data')::json->>'points')::int
    WHERE id = in_user_id;
 

  RETURN TRUE;
END;
$$ LANGUAGE plpgsql;

Запрос

select update_user(1, '{"json_data": {"name": "FITGAME", "gold": 100, "energy": 50, "points": 300}}');

Топ лучших#

Хранимая процедура для обновления профиля игрока

CREATE OR REPLACE FUNCTION get_top(in_type text, in_val integer)
RETURNS JSONB AS $$
DECLARE out_json JSONB = '{}';
  json_list JSONB;
  place_num JSONB;
BEGIN

  IF in_type = 'points' THEN

    SELECT json_agg(row_to_json(t)) INTO json_list 
    FROM (
      SELECT json_data FROM users ORDER BY points DESC LIMIT 100
    ) t;

    SELECT count(1) INTO place_num FROM users WHERE points >= in_val;

  END IF;


  IF json_list IS NOT NULL THEN
    out_json = jsonb_set(out_json, '{list}', json_list, true);
  ELSE
    out_json = jsonb_set(out_json, '{list}', '[]', true);
  END IF;


  IF place_num IS NOT NULL THEN 
    out_json = jsonb_set(out_json, '{pos}', place_num, true);
  ELSE
    out_json = jsonb_set(out_json, '{pos}', -1, true);
  END IF;

  RETURN out_json;

END;
$$ LANGUAGE plpgsql STABLE;

Запрос

select get_top('points', 5);