153 lines
5.7 KiB
JavaScript
153 lines
5.7 KiB
JavaScript
/**
|
|
* @type {import('node-pg-migrate').ColumnDefinitions | undefined}
|
|
*/
|
|
export const shorthands = undefined;
|
|
|
|
/**
|
|
* @param pgm {import('node-pg-migrate').MigrationBuilder}
|
|
* @param run {() => void | undefined}
|
|
* @returns {Promise<void> | void}
|
|
*/
|
|
export const up = (pgm) => {
|
|
// Создание расширения для генерации UUID
|
|
pgm.createExtension('pgcrypto', { ifNotExists: true });
|
|
|
|
// Таблица пользователей
|
|
pgm.createTable('users', {
|
|
id: { type: 'uuid', primaryKey: true, default: pgm.func('gen_random_uuid()') },
|
|
telegram_id: { type: 'bigint', notNull: true, unique: true },
|
|
username: { type: 'varchar(255)' },
|
|
first_name: { type: 'varchar(255)' },
|
|
last_name: { type: 'varchar(255)' },
|
|
language_code: { type: 'varchar(10)', default: 'en' },
|
|
is_active: { type: 'boolean', default: true },
|
|
created_at: { type: 'timestamp', default: pgm.func('NOW()') },
|
|
last_active_at: { type: 'timestamp', default: pgm.func('NOW()') },
|
|
updated_at: { type: 'timestamp', default: pgm.func('NOW()') },
|
|
premium: { type: 'boolean', default: false },
|
|
premium_expires_at: { type: 'timestamp' }
|
|
});
|
|
|
|
// Таблица профилей
|
|
pgm.createTable('profiles', {
|
|
id: { type: 'uuid', primaryKey: true, default: pgm.func('gen_random_uuid()') },
|
|
user_id: { type: 'uuid', references: 'users(id)', onDelete: 'CASCADE' },
|
|
name: { type: 'varchar(255)', notNull: true },
|
|
age: {
|
|
type: 'integer',
|
|
notNull: true,
|
|
check: 'age >= 18 AND age <= 100'
|
|
},
|
|
gender: {
|
|
type: 'varchar(10)',
|
|
notNull: true,
|
|
check: "gender IN ('male', 'female', 'other')"
|
|
},
|
|
interested_in: {
|
|
type: 'varchar(10)',
|
|
notNull: true,
|
|
check: "interested_in IN ('male', 'female', 'both')"
|
|
},
|
|
looking_for: {
|
|
type: 'varchar(20)',
|
|
default: 'both',
|
|
check: "looking_for IN ('male', 'female', 'both')"
|
|
},
|
|
bio: { type: 'text' },
|
|
photos: { type: 'jsonb', default: '[]' },
|
|
interests: { type: 'jsonb', default: '[]' },
|
|
city: { type: 'varchar(255)' },
|
|
education: { type: 'varchar(255)' },
|
|
job: { type: 'varchar(255)' },
|
|
height: { type: 'integer' },
|
|
religion: { type: 'varchar(255)' },
|
|
dating_goal: { type: 'varchar(255)' },
|
|
smoking: { type: 'boolean' },
|
|
drinking: { type: 'boolean' },
|
|
has_kids: { type: 'boolean' },
|
|
location_lat: { type: 'decimal(10,8)' },
|
|
location_lon: { type: 'decimal(11,8)' },
|
|
search_min_age: { type: 'integer', default: 18 },
|
|
search_max_age: { type: 'integer', default: 50 },
|
|
search_max_distance: { type: 'integer', default: 50 },
|
|
is_verified: { type: 'boolean', default: false },
|
|
is_visible: { type: 'boolean', default: true },
|
|
created_at: { type: 'timestamp', default: pgm.func('NOW()') },
|
|
updated_at: { type: 'timestamp', default: pgm.func('NOW()') }
|
|
});
|
|
|
|
// Таблица свайпов
|
|
pgm.createTable('swipes', {
|
|
id: { type: 'uuid', primaryKey: true, default: pgm.func('gen_random_uuid()') },
|
|
user_id: { type: 'uuid', references: 'users(id)', onDelete: 'CASCADE' },
|
|
target_user_id: { type: 'uuid', references: 'users(id)', onDelete: 'CASCADE' },
|
|
type: {
|
|
type: 'varchar(20)',
|
|
notNull: true,
|
|
check: "type IN ('like', 'pass', 'superlike')"
|
|
},
|
|
created_at: { type: 'timestamp', default: pgm.func('NOW()') },
|
|
is_match: { type: 'boolean', default: false }
|
|
});
|
|
pgm.addConstraint('swipes', 'unique_swipe', {
|
|
unique: ['user_id', 'target_user_id']
|
|
});
|
|
|
|
// Таблица матчей
|
|
pgm.createTable('matches', {
|
|
id: { type: 'uuid', primaryKey: true, default: pgm.func('gen_random_uuid()') },
|
|
user_id_1: { type: 'uuid', references: 'users(id)', onDelete: 'CASCADE' },
|
|
user_id_2: { type: 'uuid', references: 'users(id)', onDelete: 'CASCADE' },
|
|
created_at: { type: 'timestamp', default: pgm.func('NOW()') },
|
|
last_message_at: { type: 'timestamp' },
|
|
is_active: { type: 'boolean', default: true },
|
|
is_super_match: { type: 'boolean', default: false },
|
|
unread_count_1: { type: 'integer', default: 0 },
|
|
unread_count_2: { type: 'integer', default: 0 }
|
|
});
|
|
pgm.addConstraint('matches', 'unique_match', {
|
|
unique: ['user_id_1', 'user_id_2']
|
|
});
|
|
|
|
// Таблица сообщений
|
|
pgm.createTable('messages', {
|
|
id: { type: 'uuid', primaryKey: true, default: pgm.func('gen_random_uuid()') },
|
|
match_id: { type: 'uuid', references: 'matches(id)', onDelete: 'CASCADE' },
|
|
sender_id: { type: 'uuid', references: 'users(id)', onDelete: 'CASCADE' },
|
|
receiver_id: { type: 'uuid', references: 'users(id)', onDelete: 'CASCADE' },
|
|
content: { type: 'text', notNull: true },
|
|
message_type: {
|
|
type: 'varchar(20)',
|
|
default: 'text',
|
|
check: "message_type IN ('text', 'photo', 'gif', 'sticker')"
|
|
},
|
|
created_at: { type: 'timestamp', default: pgm.func('NOW()') },
|
|
is_read: { type: 'boolean', default: false }
|
|
});
|
|
|
|
// Создание индексов
|
|
pgm.createIndex('users', 'telegram_id');
|
|
pgm.createIndex('profiles', 'user_id');
|
|
pgm.createIndex('profiles', ['location_lat', 'location_lon'], {
|
|
where: 'location_lat IS NOT NULL AND location_lon IS NOT NULL'
|
|
});
|
|
pgm.createIndex('profiles', ['age', 'gender', 'interested_in']);
|
|
pgm.createIndex('swipes', ['user_id', 'target_user_id']);
|
|
pgm.createIndex('matches', ['user_id_1', 'user_id_2']);
|
|
pgm.createIndex('messages', ['match_id', 'created_at']);
|
|
};
|
|
|
|
/**
|
|
* @param pgm {import('node-pg-migrate').MigrationBuilder}
|
|
* @param run {() => void | undefined}
|
|
* @returns {Promise<void> | void}
|
|
*/
|
|
export const down = (pgm) => {
|
|
pgm.dropTable('messages');
|
|
pgm.dropTable('matches');
|
|
pgm.dropTable('swipes');
|
|
pgm.dropTable('profiles');
|
|
pgm.dropTable('users');
|
|
pgm.dropExtension('pgcrypto');
|
|
};
|