Sequelize: отношения «многие ко многим» между MariaDB и Postgres - PullRequest
0 голосов
/ 23 июня 2019

История вопроса
Вот мой сценарий, у меня есть база данных с именем Location в моем MariaDB, и у меня есть база данных User в моем Postgres. Я хочу связать два из них в моей базе данных Postgres. Итак, у меня есть две таблицы users и userLocations. О, да, приятно отметить, что У меня есть доступ только для чтения (SELECT и CREATE VIEW) из LocationDB и подключения к UserDB от имени пользователя root. Да, я успешно выполнил оба из них. Я даже смог получить данные от LocationDB, но единственная проблема сейчас заключается в создании этого отношения между User и Location. Журналы ошибок доступны внизу.

Вот мои модели:
models/user.js

// ... Connection to UserDB (uses Postgres)
const UserDB = require('../datasources/user-db')

const User = UserDB.define('user', {
  id: { type: Sequelize.INTEGER, primaryKey: true, autoIncrement: true },
  name: { type: Sequelize.STRING, allowNull: false }
})
module.exports = User

models/location.js

// Connection to LocationDB (uses MariaDB)
const LocationDB = require('../datasources/location-db')

const Location = LocationDB.define('ms_location', {
  id_Location: { type: Sequelize.INTEGER, primaryKey: true },
  name_Location: { type: Sequelize.STRING, allowNull: false }
}, { timestamps: false, freezeTableName: true })
module.exports = Location

models/user-location.js

// ... Connection to UserDB (uses Postgres)
const UserDB = require('../datasources/user-db')

const UserLocation = UserDB.define('userLocation', {
  id: { type: Sequelize.INTEGER, primaryKey: true, autoIncrement: true }
})
module.exports = UserLocation

app.js

const Location = require('./models/location')
const User     = require('./models/user')
const UserLocation = require('./models/user-location')

User.belongsToMany(Location, { through: UserLocation })

Это сокращенная версия кейса, если вам нужна дополнительная информация, пожалуйста, спросите, так как я все еще плохо знаком с sequelize

Журнал ошибок: (извините, я не представляю, как его украсить)

{ SequelizeDatabaseError: relation "ms_location" does not exist
    at Query.formatError (<path-to-project>/node_modules/.registry.npmjs.org/sequelize/5.8.6/node_modules/sequelize/lib/dialects/postgres/query.js:354:16)
    at query.catch.err (<path-to-project>/node_modules/.registry.npmjs.org/sequelize/5.8.6/node_modules/sequelize/lib/dialects/postgres/query.js:71:18)
    at tryCatcher (<path-to-project>/node_modules/.registry.npmjs.org/bluebird/3.5.5/node_modules/bluebird/js/release/util.js:16:23)
    at Promise._settlePromiseFromHandler (<path-to-project>/node_modules/.registry.npmjs.org/bluebird/3.5.5/node_modules/bluebird/js/release/promise.js:517:31)
    at Promise._settlePromise (<path-to-project>/node_modules/.registry.npmjs.org/bluebird/3.5.5/node_modules/bluebird/js/release/promise.js:574:18)
    at Promise._settlePromise0 (<path-to-project>/node_modules/.registry.npmjs.org/bluebird/3.5.5/node_modules/bluebird/js/release/promise.js:619:10)
    at Promise._settlePromises (<path-to-project>/node_modules/.registry.npmjs.org/bluebird/3.5.5/node_modules/bluebird/js/release/promise.js:695:18)
    at _drainQueueStep (<path-to-project>/node_modules/.registry.npmjs.org/bluebird/3.5.5/node_modules/bluebird/js/release/async.js:138:12)
    at _drainQueue (<path-to-project>/node_modules/.registry.npmjs.org/bluebird/3.5.5/node_modules/bluebird/js/release/async.js:131:9)
    at Async._drainQueues (<path-to-project>/node_modules/.registry.npmjs.org/bluebird/3.5.5/node_modules/bluebird/js/release/async.js:147:5)
    at Immediate.Async.drainQueues [as _onImmediate] (<path-to-project>/node_modules/.registry.npmjs.org/bluebird/3.5.5/node_modules/bluebird/js/release/async.js:17:14)
    at runCallback (timers.js:705:18)
    at tryOnImmediate (timers.js:676:5)
    at processImmediate (timers.js:658:5)
  name: 'SequelizeDatabaseError',
  parent:
   { error: relation "ms_location" does not exist
       at Connection.parseE (<path-to-project>/node_modules/.registry.npmjs.org/pg/7.11.0/node_modules/pg/lib/connection.js:602:11)
       at Connection.parseMessage (<path-to-project>/node_modules/.registry.npmjs.org/pg/7.11.0/node_modules/pg/lib/connection.js:399:19)
       at Socket.<anonymous> (<path-to-project>/node_modules/.registry.npmjs.org/pg/7.11.0/node_modules/pg/lib/connection.js:121:22)
       at Socket.emit (events.js:189:13)
       at addChunk (_stream_readable.js:284:12)
       at readableAddChunk (_stream_readable.js:265:11)
       at Socket.Readable.push (_stream_readable.js:220:10)
       at TCP.onStreamRead [as onread] (internal/stream_base_commons.js:94:17)
     name: 'error',
     length: 107,
     severity: 'ERROR',
     code: '42P01',
     detail: undefined,
     hint: undefined,
     position: undefined,
     internalPosition: undefined,
     internalQuery: undefined,
     where: undefined,
     schema: undefined,
     table: undefined,
     column: undefined,
     dataType: undefined,
     constraint: undefined,
     file: 'namespace.c',
     line: '426',
     routine: 'RangeVarGetRelidExtended',
     sql:
      'CREATE TABLE IF NOT EXISTS "userLocations" ("id"  SERIAL , "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL, "userId" INTEGER REFERENCES "users" ("id") ON DELETE CASCADE ON UPDATE CASCADE, "msLocationIdLocation" INTEGER REFERENCES "ms_location" ("id_Location") ON DELETE CASCADE ON UPDATE CASCADE, UNIQUE ("userId", "msLocationIdLocation"), PRIMARY KEY ("id"));' },
  original:
   { error: relation "ms_location" does not exist
       at Connection.parseE (<path-to-project>/node_modules/.registry.npmjs.org/pg/7.11.0/node_modules/pg/lib/connection.js:602:11)
       at Connection.parseMessage (<path-to-project>/node_modules/.registry.npmjs.org/pg/7.11.0/node_modules/pg/lib/connection.js:399:19)
       at Socket.<anonymous> (<path-to-project>/node_modules/.registry.npmjs.org/pg/7.11.0/node_modules/pg/lib/connection.js:121:22)
       at Socket.emit (events.js:189:13)
       at addChunk (_stream_readable.js:284:12)
       at readableAddChunk (_stream_readable.js:265:11)
       at Socket.Readable.push (_stream_readable.js:220:10)
       at TCP.onStreamRead [as onread] (internal/stream_base_commons.js:94:17)
     name: 'error',
     length: 107,
     severity: 'ERROR',
     code: '42P01',
     detail: undefined,
     hint: undefined,
     position: undefined,
     internalPosition: undefined,
     internalQuery: undefined,
     where: undefined,
     schema: undefined,
     table: undefined,
     column: undefined,
     dataType: undefined,
     constraint: undefined,
     file: 'namespace.c',
     line: '426',
     routine: 'RangeVarGetRelidExtended',
     sql:
      'CREATE TABLE IF NOT EXISTS "userLocations" ("id"  SERIAL , "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL, "userId" INTEGER REFERENCES "users" ("id") ON DELETE CASCADE ON UPDATE CASCADE, "msLocationIdLocation" INTEGER REFERENCES "ms_location" ("id_Location") ON DELETE CASCADE ON UPDATE CASCADE, UNIQUE ("userId", "msLocationIdLocation"), PRIMARY KEY ("id"));' },
  sql:
   'CREATE TABLE IF NOT EXISTS "userLocations" ("id"  SERIAL , "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL, "userId" INTEGER REFERENCES "users" ("id") ON DELETE CASCADE ON UPDATE CASCADE, "msLocationIdLocation" INTEGER REFERENCES "ms_location" ("id_Location") ON DELETE CASCADE ON UPDATE CASCADE, UNIQUE ("userId", "msLocationIdLocation"), PRIMARY KEY ("id"));' }

1 Ответ

1 голос
/ 23 июня 2019

Вы сказали Sequelize, что у вас есть таблица с именем user и таблица с именем msLocation и что они связаны через другую таблицу с именем userLocation.(Или это userLocations? Ваш код и сообщение об ошибке несовместимы.)

Похоже, что Sequelize пытается создать userLocations таблицу UserDB, но не удается, потому что, как часть определения таблицы,он пытается создать ссылку на внешний ключ для ms_location:

"msLocationIdLocation" INTEGER REFERENCES "ms_location" ("id_Location")
ON DELETE CASCADE ON UPDATE CASCADE

, что не удается, поскольку ms_location находится не в UserDB, а в другой базе данных.

Я не знаю,Sequelize может фактически обрабатывать таблицы, охватывающие несколько серверов баз данных, но я сомневаюсь в этом.Создать запрос, охватывающий две таблицы в одной базе данных, легко, Sequelize может просто создать объединение.Это совершенно другая история, если таблицы находятся на двух разных серверах;теперь Sequelize должен был бы выполнить два разных запроса и выполнить всю логику соединения в памяти.Это довольно большой подъем.

В некоторых базах данных есть способ создать таблицу в одной базе данных, которая реплицируется или пересылается в таблицу в другой базе данных.Если PostgreSQL поддерживает это, вы можете попробовать использовать его для репликации или теневого копирования таблицы MariaDB, что позволит Sequelize видеть все таблицы как часть UserDB.

...