Bruno Mazzardo
Bruno Mazzardo

Reputation: 1586

Sequelize relationship error

I'm writing an express API, with sequelize and postgresl, postgresl is being hosted at Heroku.

When I try to create a relationship between those tables below, it gives me this error

Unhandled rejection SequelizeDatabaseError: relation "questions" does not exist

The idea is that a question has an id, a title, a score, has many answers, and one Right Answer.

Question Model:

import { sequelize } from "../Util/db"
import { Users } from "./User"
import { Answer } from "./Answer"
const Sequelize = require("sequelize")
const Question = sequelize.define("question", {
  id: {
    type: Sequelize.INTEGER,
    primaryKey: true,
    autoIncrement: true
  },
  title: {
    type: Sequelize.STRING
  },
  score: {
    type: Sequelize.INTEGER,
    defaultValue: 0
  },
  content: {
    type: Sequelize.JSONB
  }
})

Question.belongsTo(Users)
Question.hasMany(Answer, { as: "Answers", foreignKey: "id"})
Question.hasOne(Answer, {as: "RightAnswer", foreignKey: "id"})
Question.sync({force: false}).then(() => {
  // Table created
  console.log("Question Table Synchronized")
})


interface QuestionType {
  id: number
  title: string
  score: number
  content: string
}


export { Question, QuestionType }

Answer Model:

import { sequelize } from "../Util/db"
import { Users } from "./User"
import { Question } from "./Question"
const Sequelize = require("sequelize")
const Answer = sequelize.define("answer", {
  id: {
    type: Sequelize.INTEGER,
    primaryKey: true,
    autoIncrement: true
  },
  score: {
    type: Sequelize.INTEGER,
    defaultValue: 0
  },
  content: {
    type: Sequelize.JSONB
  }
})

Answer.belongsTo(Users)
Answer.sync({force: false}).then(() => {
  // Table created
  console.log("Answer Table Synchronized")
})


interface AnswerType {
  id: number
  score: number
  content: string
}


export { Answer, AnswerType }

Creation script, created by sequelize

Executing (default): CREATE TABLE IF NOT EXISTS "users" ("id"  SERIAL , "email" VARCHAR(255), "score" INTEGER DEFAULT 0, "name" VARCHAR(255), "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL, PRIMARY KEY ("id"));
Executing (default): CREATE TABLE IF NOT EXISTS "answers" ("id"  SERIAL  REFERENCES "questions" ("id") ON DELETE CASCADE ON UPDATE CASCADE, "score" INTEGER DEFAULT 0, "content" JSONB, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL, "userId" INTEGER REFERENCES "users" ("id") ON DELETE SET NULL ON UPDATE CASCADE, PRIMARY KEY ("id"));
Executing (default): CREATE TABLE IF NOT EXISTS "questions" ("id"  SERIAL , "title" VARCHAR(255), "score" INTEGER DEFAULT 0, "content" JSONB, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL, "userId" INTEGER REFERENCES "users" ("id") ON DELETE SET NULL ON UPDATE CASCADE, PRIMARY KEY ("id"));
Executing (default): SELECT i.relname AS name, ix.indisprimary AS primary, ix.indisunique AS unique, ix.indkey AS indkey, array_agg(a.attnum) as column_indexes, array_agg(a.attname) AS column_names, pg_get_indexdef(ix.indexrelid) AS definition FROM pg_class t, pg_class i, pg_index ix, pg_attribute a WHERE t.oid = ix.indrelid AND i.oid = ix.indexrelid AND a.attrelid = t.oid AND t.relkind = 'r' and t.relname = 'users' GROUP BY i.relname, ix.indexrelid, ix.indisprimary, ix.indisunique, ix.indkey ORDER BY i.relname;
Unhandled rejection SequelizeDatabaseError: relation "questions" does not exist
    at Query.formatError (/home/mazzardo/Codigo/pas/node-typescript-boilerplate/node_modules/sequelize/lib/dialects/postgres/query.js:363:16)
    at query.catch.err (/home/mazzardo/Codigo/pas/node-typescript-boilerplate/node_modules/sequelize/lib/dialects/postgres/query.js:86:18)
    at tryCatcher (/home/mazzardo/Codigo/pas/node-typescript-boilerplate/node_modules/bluebird/js/release/util.js:16:23)
    at Promise._settlePromiseFromHandler (/home/mazzardo/Codigo/pas/node-typescript-boilerplate/node_modules/bluebird/js/release/promise.js:512:31)
    at Promise._settlePromise (/home/mazzardo/Codigo/pas/node-typescript-boilerplate/node_modules/bluebird/js/release/promise.js:569:18)
    at Promise._settlePromise0 (/home/mazzardo/Codigo/pas/node-typescript-boilerplate/node_modules/bluebird/js/release/promise.js:614:10)
    at Promise._settlePromises (/home/mazzardo/Codigo/pas/node-typescript-boilerplate/node_modules/bluebird/js/release/promise.js:689:18)
    at Async._drainQueue (/home/mazzardo/Codigo/pas/node-typescript-boilerplate/node_modules/bluebird/js/release/async.js:133:16)
    at Async._drainQueues (/home/mazzardo/Codigo/pas/node-typescript-boilerplate/node_modules/bluebird/js/release/async.js:143:10)
    at Immediate.Async.drainQueues (/home/mazzardo/Codigo/pas/node-typescript-boilerplate/node_modules/bluebird/js/release/async.js:17:14)
    at runCallback (timers.js:651:20)
    at tryOnImmediate (timers.js:624:5)
    at processImmediate [as _immediateCallback] (timers.js:596:5)
Executing (default): SELECT i.relname AS name, ix.indisprimary AS primary, ix.indisunique AS unique, ix.indkey AS indkey, array_agg(a.attnum) as column_indexes, array_agg(a.attname) AS column_names, pg_get_indexdef(ix.indexrelid) AS definition FROM pg_class t, pg_class i, pg_index ix, pg_attribute a WHERE t.oid = ix.indrelid AND i.oid = ix.indexrelid AND a.attrelid = t.oid AND t.relkind = 'r' and t.relname = 'questions' GROUP BY i.relname, ix.indexrelid, ix.indisprimary, ix.indisunique, ix.indkey ORDER BY i.relname;
User Table Synchronized
Question Table Synchronized

Side note, I'm using typescript on the project

Upvotes: 1

Views: 1271

Answers (1)

AbhinavD
AbhinavD

Reputation: 7282

This could be because of a race condition with each sync. Each call to sync in asynchronous and since we have foreign key constraints, it is possible that one of the table is not created which is looking for association. I think you should use

sequelize.sync() which should solve your issue.

From the docs

Because Sequelize is doing a lot of magic, you have to call Sequelize.sync after setting the associations! Doing so will allow you the following:

Upvotes: 2

Related Questions