Hi,
Мы планируем создать мультитенантный продукт SaaS.
Подождите, что называется мультитенантным и SaaS? - Пожалуйста, погуглите 🙏🏼
Сначала мы проектируем прототип приложения. Дизайн классный. 😍
Во-вторых, мы планируем это реализовать.
Изначально мы выбираем стек MEAN для создания этого продукта вместо «Mongo», мы выбираем «MySQL» 😌
Но мы не знаем, как спроектировать архитектуру базы данных с несколькими арендаторами. Мы запутались.
Позже мы погуглили «как построить, как реализовать, как… ..»
Наконец-то у нас появилась идея!
Существует три основных распространенных архитектуры для создания мультитенантного приложения.
- Отдельная база данных для каждого клиента
- Одна база данных, но отдельная таблица для каждого клиента
- Единая база данных и одни и те же таблицы для всех клиентов, но у нас есть tenant_id во всех таблицах, поэтому мы запрашиваем данные в соответствии с конкретным клиентом.
Выбираем вариант 2.
И снова мы погуглили, «как создавать отдельные таблицы для каждого клиента в MySQL».
К тому времени мы обнаружили, что в Postgres есть концепция под названием «схемы» - единая база данных, внутри которой мы можем создавать несколько схем, называемых client1schema, client2schema… и т. Д. Внутри этих схем у нас есть отдельные таблицы.
ИДЕАЛЬНО 🔥
Итак, наконец, мы начали писать код.
Как создавать динамические схемы?
В мою заявку входит новый пользователь, он вводит данные для регистрации
имя пользователя, электронная почта, пароль, телефон.
Мы получаем детали с помощью AngularJs, поэтому мы отправляем эти данные на мой экспресс-сервер.
Код AngularJs:
$http.post('/api/signup/', datas) .then(() => { }) .catch(() => { });
узел / экспресс:
app.post('/api/signup', api.signup);
Структуры таблиц и подключение к базе данных:
// Table structures // client app postgres const db = new Sequelize(config.postgres_db, config.postgres_user, config.postgres_pwd, { host: config.postgres_host, port: 5432, dialect: 'postgres', logging: false, }); db.authenticate().then((err) => { if (err) { console.log('There is connection in ERROR.'); } else { console.log('Postgres Client App Connection has been established successfully'); } }); db.sync().then(() => { console.log('Psql Client App Missing Table Created'); }, (err) => { console.log('An error occurred while creating postgres client app table:', err.message); }); const Business = db.define('business', { username: Sequelize.STRING, }); const Login = db.define('login', { username: Sequelize.STRING, email: Sequelize.STRING, mobile: Sequelize.STRING, password: Sequelize.STRING, }); exports.signup = (req, res) => { // in req.body i have all details 'name, email....'; // now checking whether username already exists or not. Business.findOrCreate({ where: { username: req.body.username, }, defaults: { username: req.body.username, }, }).spread((user, created) => { if (created) { createSchema(req, res); // function } else { res.status(400).send(`${req.body.username} already exists.`); } }).catch(err => res.status(400).send(err.message)); }; // This below function will create schema dynamically. const createSchema = async (req, res) => { await db.createSchema(req.body.username).then(async () => { await Object.keys(db.models).forEach((currentItem) => { db.models[currentItem].schema(req.body.username).sync(); }); const loginDetails = { username: req.body.username, password: encrypt(req.body.password), email: req.body.email, mobile: req.body.mobile, }; const loginSchema = db.models.login.schema(req.body.username); loginSchema.create(loginDetails) .then((loginData) => { res.status(200).send(loginData); }) .catch((err) => { console.log('error :', err.message); }); }); };
Например, если имя пользователя введено как «sameer», создается схема с именем «sameer».
Подключите базу данных psql через командную строку и нажмите \ dn.
Да, у нас есть схема под названием «sameer» с отдельными таблицами.
выберите * из sameer.logins; вы увидите подробности.
Теперь, как динамически получить конкретную схему определенных пользователей?
Перейдем к разделу входа:
Теперь пользователь переходит в раздел входа в систему, теперь он вводит имя пользователя и пароль и нажимает кнопку входа в систему!
Я использую password.js для аутентификации.
// login passport api exports.Login = (req) => { console.log(req.body.username); // sameer db.models.login.schema(req.body.username).find({ where: { username: req.body.username, }, raw: true, }).then(() => { // your stuffs....logics... }) };
Эй, вот и все, что у нас получилось!
у нас есть сеанс req.user в паспорте.js.
Итак, если вы хотите использовать операции CRUD с помощью Sequelize
вместо использования Table.create или Table.find и т. д.
Используйте этот формат ниже
db.models.table.schema(req.user.username).create( ... your logics ) db.models.table.schema(req.user.username).find(... your logics) db.models.table.schema(req.user.username).update(... your logics) db.models.table.schema(req.user.username).update(... your logics)
Спасибо за прочтение :)