Scenario: I am dealing with a database which is running both postgres and infobright, where infobright is set to default engine.
Goal: Have Sequelize create a table in postgres
Problem: Sequelize is creating table in Infobright by default.
Detailed Explanation:
So when I am trying to define a model which look like:
sequelize.define('mymodel', {
file_name: {
type: Sequelize.STRING,
}
}, {
schema: 'myschema'
});
The sql that get generated looks like:
create
table
if not exists "myschema"."mymodel"(
"id" serial,
"file_name" varchar(255),
"createdAt" timestamp with time zone not null,
"updatedAt" timestamp with time zone not null,
primary key("id")
);
NOTE: Because with (engine = postgres) is missing, the system tries to create table in the default engine i.e. infobright, which is not what I expect it to do.
Expected SQL
create
table
if not exists "myschema"."mymodel"(
"id" serial,
"file_name" varchar(255),
"createdAt" timestamp with time zone not null,
"updatedAt" timestamp with time zone not null,
primary key("id")
) with (
engine = postgres
);
Note: Executing the above generates a table in postgres.
I tried specifying engine in sequelize as well as model configuration, but it doesn't work.
Questions: How shall I configure Sequelize or my model so that it generates the expected sql. Open to other suggestions as well.
Related
I'm making a simple multiplayer game using postgres as a database (and node as the BE if that helps). I made the table users which contains all of the user accounts, and a table equipped, which contains all of the equipped items a user has. users has a one -> many relationship with equipped.
I'm running into the situation where I need the data from both tables structured like so:
[
{
user_id: 1,
user_data...
equipped: [
{ user_id: 1, item_data... },
...
],
},
{
user_id: 2,
user_data...
equipped: [
{ user_id: 2, item_data... },
...
],
},
]
Is there a way to get this data in a single query? Is it a good idea to get it in a single query?
EDIT: Here's my schemas
CREATE TABLE IF NOT EXISTS users (
user_id SERIAL PRIMARY KEY,
username VARCHAR(100) UNIQUE NOT NULL,
password VARCHAR(100) NOT NULL,
email VARCHAR(100) NOT NULL,
created_on TIMESTAMP NOT NULL DEFAULT NOW(),
last_login TIMESTAMP,
authenticated BOOLEAN NOT NULL DEFAULT FALSE,
reset_password_hash UUID
);
CREATE TABLE IF NOT EXISTS equipment (
equipment_id SERIAL PRIMARY KEY NOT NULL,
inventory_id INTEGER NOT NULL REFERENCES inventory (inventory_id) ON DELETE CASCADE,
user_id INTEGER NOT NULL REFERENCES users (user_id) ON DELETE CASCADE,
slot equipment_slot NOT NULL,
created_on TIMESTAMP NOT NULL DEFAULT NOW(),
CONSTRAINT only_one_item_per_slot UNIQUE (user_id, slot)
);
Okay so what I was looking for was closer to postgresql json aggregate, but I didn't know what to look for.
Based on my very limited SQL experience, the "classic" way to handle this would just to do a simple JOIN query on the database like so:
SELECT users.username, equipment.slot, equipment.inventory_id
FROM users
LEFT JOIN equipment ON users.user_id = equipment.user_id;
This is nice and simple, but I would need to merge these tables in my server before sending them off.
Thankfully postgres lets you aggregate rows into a JSON array, which is exactly what I needed (thanks #j-spratt). My final* query looks like:
SELECT users.username,
json_agg(json_build_object('slot', equipment.slot, 'inventory_id', equipment.inventory_id))
FROM users
LEFT JOIN equipment ON users.user_id = equipment.user_id
GROUP BY users.username;
Which returns in exactly the format I was looking for.
I'm running PostgreSQL 11, and attempting to update one of its table entries using Sequelize.
My NodeJS code:
require('env2')('.env');
const Sequelize = require('sequelize');
const sequelize=new Sequelize(process.env.database,process.env.username,process.env.password,{
dialect:'postgres'
});
const Agent=sequelize.define('agent');
updateValues={available:false};
Agent.update(updateValues,{where:{phonenumber:'+18005551212'}}).then(result=>{console.log(result)});
The table agent has the structure:
id primary key serial,
phonenumber varchar(100),
available boolean
When I run the NodeJS code, I get this error:
Executing (default): UPDATE "agents" SET "updatedAt"='2018-12-27 10:16:54.504 +0
0:00' WHERE "phonenumber" = '+18005551212'
Unhandled rejection SequelizeDatabaseError: relation "agents" does not exist
Why is this update failing? I don't understand why the error is talking about the relation "agents", when I provided the table name as "agent" in sequelize.define(agent).
The update is successful when I use raw SQL as follows:
sequelize.query("update agent set available=false where phonenumber='+18005551212'").then(result=>{
console.log(result);
});
By default sequelize creates a table with a plural of its definition name, so when you do sequelize.define('agent') it actually creates a table with name agents . If you don't want to change your table name naturally you can use freezeTableName: true option in sequelize definition. More can be found in this answer. Refer Sequelize configuration doc
.
Here is my model ,
var traders = sequelize.define('traders', {
.....
}, {});
it has many to many self association
traders.belongsToMany(models.traders,{
as:'feedbackClient',
through:'feedback'
});
idea is one trader can give feedback to other trader on each successful trade.
but when i sync it generates table with this SQL query
Executing (default): CREATE TABLE IF NOT EXISTS "feedbacks" ("id" S`ERIAL , "rating" "public"."enum_feedbacks_rating", "comment" VARCHAR(255), "traderId" INTEGER REFERENCES "traders" ("id") ON DELETE CASCADE ON UPDATE CASCADE, "feedbackClientId" INTEGER REFERENCES "traders" ("id") ON DELETE CASCADE ON UPDATE CASCADE, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL, UNIQUE ("traderId", "feedbackClientId"), PRIMARY KEY ("id"));`
how can i remove this constraint?
UNIQUE ("traderId", "feedbackClientId")
so that i can add multiple records with same combination of traderId and feedbackClientId.
Got a solution here, please post your answers if you have better solutions.
I am new in node.js, i want to fetch the data from table of the postgresql using sequelize ORM in node.js. I am using below code but its not working.
const apisListModel = sequelize.define('apisList', {});
apisListModel.findAll().then((data)=>{
JSON.stringify(data,undefined,2);
},(e)=>{
console.log(e);
});
Its give me error
Executing (default): SELECT "id", "createdAt", "updatedAt" FROM
"apisLists" AS "apisList";
{ SequelizeDatabaseError: relation "apisLists" does not exist
But apiList table exist in my DATABASE
Sequelize changes the tableName to plural implicitly. You can define options as
const apisListModel = sequelize.define('apisList', {}, {
tableName: 'apisList'
})
The query trying to fetch data from apisLists but your table name is apiList. Note the "s" in table name.
If this is the case, you can specify the table name using the option
tableName: 'apiList'
Here is the Documentation link
I'm using the Sequelize ORM in NodeJS to manage a postgreSQL database.
I'm using the JSONB datatype in my table, I need an index on the JSONB field and an unique constraint on a property of this JSON.
If I have to do in a classic SQL here my script :
CREATE TABLE tableJson (id SERIAL PRIMARY KEY,
content JSONB NOT NULL);
CREATE INDEX j_idx ON tableJson USING gin(content jsonb_path_ops);
CREATE UNIQUE INDEX content_name_idx ON tableJson(((content->>'name')::varchar));
I've found how to create the table with the INDEX but not how to deal with the UNIQUE constraint. Here is a sample of my script :
var tableJson = sequelize.define('tableJson', {
content: Sequelize.JSONB
}, {
indexes: [{
fields: ['content'],
using: 'gin',
operator: 'jsonb_path_ops'
}
});
Is there a solution for my problem? If not I'll probably use the sequelize.query method to execute raw query but this is not very evolutive.
Any help would be appreciated!
This is the workaround I use to add indexes on JSONB fields with Postgres and Sequelize.
First, set the quoteIdentifiers option to false in your Sequelize client.
const seq = new Sequelize(db, user, pass, {
host: host,
dialect: 'postgres',
quoteIdentifiers: false,
});
(Watch out though, this will make all your table names case insensitive when created by Sequelize.sync())
You can now add indexes on JSONB fields this way in your model definition :
indexes: [
{
fields: ['content'],
using: 'gin',
operator: 'jsonb_path_ops'
},
{
fields: ['((content->>\'name\')::varchar)'],
unique: true,
name: 'content_name_idx',
}
],