#javascript #node.js #express #sequelize.js #sequelize-cli
#javascript #node.js #экспресс #sequelize.js #sequelize-cli
Вопрос:
У меня есть 2 разные базы данных, на 2 разных серверах, с 2 разными схемами.
По сути, я хочу связать одну таблицу в одной базе данных с другой таблицей в другой базе данных, хотя у меня возникают некоторые проблемы с этим. Мне удалось создать ассоциации между 2 таблицами в 2 разных базах данных на одном сервере, возникли проблемы, когда они не используют один и тот же хост / сервер.
Я не совсем уверен, что это вообще возможно, но я надеюсь, что есть способ обойти это?
Ниже приведена моя архитектура, в которой указаны 2 сервера, 2 базы данных и отсутствует связь между property
amp; favourites
-------------------- --------------------
| Server-1 | Server-2 |
-------------------- --------------------
| Database-1 | Database-2 |
-------------------- --------------------
| property <----------------- favourites |
| user | notes |
| account | |
-------------------- --------------------
Я следил за этой статьей в качестве отправной точки, хотя она, к сожалению, не охватывает мой вариант использования.
Вот моя конфигурация, определяющая параметры, полученные из файла среды и
config.js
import accessEnv from "../utils/accessEnv";
import logger from "../utils/logger";
const defaultOptions = {
dialect: "mysql",
logging: msg => logger.debug(msg)
};
module.exports = {
/**Declaration of databases for my development environment**/
"development": {
"databases": {
"Database1": {
"database": accessEnv("DB"),
"username": accessEnv("DB_USERNAME"),
"password": accessEnv("DB_PASS"),
"host": accessEnv("DB_HOST"),
"port": accessEnv("DB_PORT"),
...defaultOptions
},
"Database2": {
"database": accessEnv("DB2"),
"username": accessEnv("DB2_USERNAME"),
"password": accessEnv("DB2_PASS"),
"host": accessEnv("DB2_HOST"),
"port": accessEnv("DB2_PORT"),
...defaultOptions
},
},
}
}
в моем продолжении, созданном index.js
для моих моделей, я немного обновил его, основываясь на статье, указанной выше, для обработки 2 разных подключений к базе данных.
models/index.js
const fs = require('fs');
const path = require('path');
const Sequelize = require('sequelize');
const { default: logger } = require('../utils/logger');
const basename = path.basename(module.filename);
const env = process.env.NODE_ENV || 'development';
const config = require(`${__dirname}/../config/config.js`)[env];
const db = {};
const databases = Object.keys(config.databases);
/** Add Databases**/
for (let i = 0; i < databases.length; i) {
let database = databases[i];
let dbPath = config.databases[database];
db[database] = new Sequelize(dbPath.database, dbPath.username, dbPath.password, dbPath);
// Authenticate db connection
db[database].authenticate()
.then(() => logger.log(`${dbPath.database} connection successful!`))
.catch((err) => logger.log(err.stack));
// Allow schemas
db[database].dialect.supports.schemas = true;
}
/**Add the Database Models**/
// Add models from database1 folder
fs
.readdirSync(__dirname '/database1')
.filter(file =>
(file.indexOf('.') !== 0) amp;amp;
(file !== basename) amp;amp;
(file.slice(-3) === '.js'))
.forEach(file => {
const model = require(path.join(__dirname '/database1', file))(db.Database1, Sequelize.DataTypes);
db[model.name] = model;
});
// Add models from database2 folder
fs
.readdirSync(__dirname '/database2')
.filter(file =>
(file.indexOf('.') !== 0) amp;amp;
(file !== basename) amp;amp;
(file.slice(-3) === '.js'))
.forEach(file => {
const model = require(path.join(__dirname '/database2', file))(db.Database2, Sequelize.DataTypes);
db[model.name] = model;
});
Object.keys(db).forEach(modelName => {
if (db[modelName].associate) {
db[modelName].associate(db);
}
});
module.exports = db;
Now for the models themselves.
Property
is in one server with theDatabase1
config.Favourites
is in another server with theDatabase2
config.
A Favourites
will have one Property
, associating by a foreignKey
of propertyId
in the Favourites
model to id
of Property
model.
models/database1/Property.js
module.exports = (sequelize, DataTypes) => {
const Property = sequelize.define("Property", {
id: {
type: DataTypes.INTEGER(11),
primaryKey: true,
allowNull: false,
autoIncrement: true
},
accountNumber: {
type: DataTypes.STRING(9),
allowNull: false,
}
}, {
schema: "property_demo",
tableName: "property",
});
Property.associate = (models) => {
Property.hasOne(models.Favourites, {
as: 'favourites',
foreignKey: 'propertyId'
});
};
return Property;
};
models/database2/Favourites.js
module.exports = (sequelize, DataTypes) => {
const Favourites = sequelize.define("Favourites", {
id: {
type: DataTypes.INTEGER(),
primaryKey: true,
allowNull: false,
autoIncrement: true
},
propertyId: {
type: DataTypes.INTEGER(11),
allowNull: false,
}
}, {
schema: "shortlists",
tableName: "favourites"
});
Favourites.associate = (models) => {
Favourites.belongsTo(models.Property, {
as: 'property',
foreignKey: 'propertyId'
});
};
return Favourites;
};
Теперь, в чем проблема. Когда я пытаюсь include
Property
использовать модель в Favourites
запросе модели, как показано ниже
import catchAsync from "../utils/catchAsync";
import Models, { Favourites } from "../models";
export const getFavourites = catchAsync(async (req, res, next) => {
const favourites = await Favourites.findAll({
include: [
{
model: Models.Property,
as: 'property',
}
]
});
return res.status(200).json({
status: 'success',
data: favourites
});
});
Я получаю следующую ошибку
"error": {
"name": "SequelizeDatabaseError",
"parent": {
"code": "ER_BAD_DB_ERROR",
"errno": 1049,
"sqlState": "42000",
"sqlMessage": "Unknown database 'property_demo'"
}
}
Я понимаю, что он ищет property_demo
on Server-2
, поскольку Favourites
модель основана на Server-2
, несмотря Property
на то, что модель находится в property_demo
схеме on Server-1
, но есть ли способ обойти это, чтобы он фильтровал правильный сервер / хост здесь?
Любая помощь будет принята с благодарностью.
Комментарии:
1. Можете ли вы выполнить такой запрос как обычный SQL-запрос?
2. MySQL не был бы моей сильной стороной, поэтому я не уверен, кроме использования ОБЪЕДИНЕННОЙ таблицы
3. В этом суть! Sequelize не может сам смешивать таблицы с двух разных серверов
4. Просто возвращаюсь к этому, добавляя
separate: true,
в качестве опции включение дляProperty
работ, если я изменю ассоциациюFavourites.hasMany(models.Property
amp; setsourceKey: 'propertyId'