I am trying to create an attribute called "provider" in my postgresql model and make its data type an Object (see code below). However, I am getting the error Error: Unrecognized datatype for attribute "segment.provider".
I'm assuming this error is happening because I haven't specified what the data type of the "provider" attribute actually is (ie: type: DataTypes.OBJECT). To my knowledge, there's nothing in the Sequelize docs that demonstrates this ask of mine. Any and all help would be most appreciated. Thanks!
module.exports = (sequelize, DataTypes) => {
const Segment = sequelize.define(
'segment',
{
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true
},
provider: {
providerName: DataTypes.STRING,
externalId: DataTypes.STRING,
email: DataTypes.STRING,
privacyPolicy: DataTypes.STRING
}
},
{
freezeTableName: true,
tableName: 'segment'
}
);
return Segment;
}
Every field defined on a model(Table) is mapped into a column on the database.
That is what sequelize basically does.
Now, is there a field on a PostgreSQL database which is an object?
For what you are trying to do, you just need to use associations between tables.
Create a new model (Table) called provider:
And add the associations as follows in the example:
module.exports = (sequelize, DataTypes) => {
const Provider = sequelize.define(
'provider',
{
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true
},
name: {
type: DataTypes.STRING
},
email: {
type: DataTypes.STRING
},
privacyPolicy: {
type: DataTypes.STRING
}
},
{
freezeTableName: true,
tableName: 'provider'
}
);
// Apply the accosiation:
Provider.hasMany /* or has one */ (Segment, {foreignKey: 'provider_id'});
return Provider;
}
And in your Segment model add a foreign key and a reference to Provider
module.exports = (sequelize, DataTypes) => {
const Segment = sequelize.define(
'segment',
{
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true
},
provider_id: {
type: DataTypes.INTEGER,
references: {
model: 'provider',
key: 'id
}
}
},
{
freezeTableName: true,
tableName: 'segment'
}
);
// Apply the accosiation:
Segment.belongsTo(Provider, {foreignKey: 'id'});
return Segment;
}
Related
I have a user, role and their relation model, when I want to insert into the relation model I get this error:
error: column "userUserId" of relation "roles_users_relationships" does not exist.
Can you help with this error?
(sorry if I wrote something wrong, this is my first question on )
This is how my model looks
Role model:
const Schema = (sequelize, DataTypes) => {
const table = sequelize.define(
"roles", {
role_id: {
type: DataTypes.UUID,
defaultValue: sequelize.literal("uuid_generate_v4()"),
primaryKey: true,
},
name: {
type: DataTypes.STRING,
allowNull: false,
}
}, {
timestamps: false
}
);
table.associate = function (models) {
table.belongsToMany(models.users, {
through: "roles_users_relationship",
foreignKey: "role_id",
});
};
return table;
};
Users model:
const Schema = (sequelize, DataTypes) => {
const table = sequelize.define(
"users", {
user_id: {
type: DataTypes.UUID,
defaultValue: sequelize.literal("uuid_generate_v4()"),
primaryKey: true,
},
name: {
type: DataTypes.STRING,
allowNull: true,
}
}, {
timestamps: false
}
);
table.associate = function (models) {
table.belongsTo(models.roles, {
through: "roles_users_relationship",
foreignKey: "user_id",
});
};
return table;
};
Roles Users relationship model:
const Schema = (sequelize, DataTypes) => {
const table = sequelize.define(
"roles_users_relationship", {
user_id: {
type: DataTypes.UUID,
allowNull: false,
},
role_id: {
type: DataTypes.UUID,
allowNull: false,
},
}, {
timestamps: false
}
);
return table;
};
In your through table you should add options in related table field:
references: {
model: User,
key: 'user_id'
}
Otherwise sequelize will do it automatically, like adding foreign key column in this way tableNamePrimaryKeyColumn in your case its 'userUserId'
I am working on an electron app and for the database, I am using sqlite3 along with sequelize. I want to establish a one-to-many relationship between two of the following models.
Item
Metric
Metrics can be liters/kilograms/units and an item can be measured in any of these metrics. So following is how I have declared the Item model.
const { Model, DataTypes } = require("sequelize");
const sequelize = require("../database/db");
const Metric = require("./metricModel");
class Item extends Model {}
Item.init(
{
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true,
},
name: {
type: DataTypes.STRING,
allowNull: false,
},
metricId: {
type: DataTypes.INTEGER,
allowNull: false,
references: {
model: "metrics",
key: "id",
},
},
available: {
type: DataTypes.FLOAT,
defaultValue: 0,
},
incoming: {
type: DataTypes.FLOAT,
defaultValue: 0,
},
},
{
sequelize,
tableName: "items",
freezeTableName: true,
}
);
Item.associate = (models) => {
Item.belongsTo(models.Metric, { foreignKey: "metricId" });
};
module.exports = Item;
And following is how I have declared the Metric
const { Model, DataTypes } = require("sequelize");
const sequelize = require("../database/db");
const Item = require("./itemModel");
class Metric extends Model {}
Metric.init(
{
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true,
},
name: {
type: DataTypes.STRING,
allowNull: false,
},
description: {
type: DataTypes.STRING(10000),
},
},
{
sequelize,
tableName: 'metrics', freezeTableName: true
}
);
Metric.associate = function (models) {
Metric.hasMany(models.Item, { foreignKey: "metricId" });
};
module.exports = Metric;
But in the logs, I can't see any association getting created.
Also on making a select query on items. like below.
const items = await Item.findAll({include: [Metric]});
I get below error
My bad, there was a duplicate column in my items model and since during debugging the table named item was present beforehand, it was working fine. If you encounter this issue, make sure all your tables are declared properly.
I'm trying to run the following code block, for some reason the query tries to insert it into a column labeled "users->user_group"."userUuid", despite the fact that I have not reference the string literal userUuid once in the project (through search not in the code base), also check columns in pg-admin (using PostgreSQL), both columns in the user_group table are user_uuid and group_uuid, both columns are also validated and populated properly.
const result = await group.findAll({
include: user,
});
Postman body returns the following error
"hint": "Perhaps you meant to reference the column "users->user_group.user_uuid".",
I have 3 models user, group and user_group. The relations have been defined per documentation and countless other articles and videos.
user model
module.exports = (sequelize, DataTypes) => {
const user = sequelize.define(
"user",
{
uuid: {
type: DataTypes.STRING,
primaryKey: true,
allowNull: false,
unique: true,
},
username: {
type: DataTypes.STRING,
unique: true,
allowNull: false,
},
{
freezeTableName: true,
}
);
user.associate = (models) => {
user.belongsToMany(models.group, {
// as: "userUuid",
through: models.user_group,
foreignKey: "user_uuid",
});
};
return user;
};
group model
module.exports = (sequelize, DataTypes) => {
const group = sequelize.define(
"group",
{
uuid: {
type: DataTypes.STRING,
primaryKey: true,
allowNull: false,
unique: true,
},
title: {
type: DataTypes.STRING,
unique: true,
allowNull: false,
},
},
{
freezeTableName: true,
}
);
group.associate = (models) => {
group.belongsToMany(models.user, {
// as: "groupUuid",
through: models.user_group,
foreignKey: "group_uuid",
});
};
return group;
};
user_group model
module.exports = (sequelize, DataTypes) => {
const user_group = sequelize.define(
"user_group",
{
uuid: {
type: DataTypes.STRING,
primaryKey: true,
allowNull: false,
unique: true,
},
user_uuid: {
type: DataTypes.STRING,
allowNull: false,
references: {
model: "user",
key: "uuid",
},
},
group_uuid: {
type: DataTypes.STRING,
allowNull: false,
references: {
model: "group",
key: "uuid",
},
},
author: {
type: DataTypes.STRING,
unique: true,
allowNull: true,
},
},
{
freezeTableName: true,
}
);
user_group.associate = (models) => {
user_group.belongsTo(models.user, {
foreignKey: "user_uuid",
});
user_group.belongsTo(models.group, {
foreignKey: "group_uuid",
});
};
return user_group;
};
Any help is much apprecaited, thanks!
You should indicate otherKey option along with foreignKey in belongsToMany in order to indicate a foreign key column on the other model otherwise you will end up with a default name of an other key, see below:
The name of the foreign key in the join table (representing the target model) or an object representing the type definition for the other column (see Sequelize.define for syntax). When using an object, you can add a name property to set the name of the column. Defaults to the name of target + primary key of target (your case: user+uuid)
group.belongsToMany(models.user, {
// as: "groupUuid",
through: models.user_group,
foreignKey: "group_uuid",
otherKey: "user_uuid"
});
const result = await group.findAll({
include: {user},
});
you should to create like this. baecause you missing this {}.
i am new to sequelize, i have a user table , address table and address type table as given below.
A user can have 2 a different address , permanent and current address, and the type of address (permanent or current ) is specified in the table address type.
I have tried to access the data from mapping table (address_type) in the resolver based on schema and set hasMany relation from user -> address table , but graphql shows association not found error.
How can we get the relation properly in order to get the mapping address type name.
type User{
id:Int
name:String
}
type Address {
id: ID!
user_id:Int
city: String
addr_type:AddressType
}
type AddressType{
id : Int
name:String (permanent|current)
}
table definition
module.exports = function(sequelize, DataTypes) {
return sequelize.define('user', {
id: {
type: DataTypes.INTEGER, allowNull: false, primaryKey: true, autoIncrement: true
},
name: {
type: DataTypes.INTEGER, allowNull: false,
},
}, {
tableName: 'user',
timestamps: false
});
};
module.exports = function(sequelize, DataTypes) {
return sequelize.define('address', {
id: {
type: DataTypes.INTEGER, allowNull: false, primaryKey: true, autoIncrement: true
},
user_id: {
type: DataTypes.INTEGER, allowNull: false, field:"addr_type"
},
addr_type: {
type: DataTypes.INTEGER, allowNull: false, field:"addr_type"
},
city: {
type: DataTypes.STRING, allowNull: false,
},
}, {
tableName: 'address',
timestamps: false
});
};
module.exports = function(sequelize, DataTypes) {
return sequelize.define('address_types', {
id: {
type: DataTypes.INTEGER, allowNull: false, primaryKey: true, autoIncrement: true
},
name: {
type: DataTypes.STRING, allowNull: false,
},
}, {
tableName: 'address_type',
timestamps: false
});
};
relationship
db.user.hasMany(db.address,{foreignKey: 'user_id'});
db.address.belongsTo(db.user,{foreignKey: 'user_id'});
db.address.belongsTo(db.address_types,{foreignKey: 'addr_type'});
resolver code
userts: async (obj, args, context, info ) => User.findAll( {
where: { user_status: 1 },
,
raw: true,
nest: true,
} ).then(userts => {
const response = userts.map(usert => {
return{
// i have 15 fields for a user, if i can access the schema of the corresponsing resolver i can dynamically build the response out put
id: usert.id,
firstName: usert.firstName,
lastName: usert.lastName,
middleName: usert.middleName,
}
})
return response;
}),
You should turn off the option raw in order to get associated objects and use the include option to indicate what associated models you wish to load.
User.findAll( {
where: { user_status: 1 },
include: [{
model: Address,
include: AddressType
}],
raw: false,
nest: true,
}
I have a postrgresql/Sequelize model called Segment, which belongs to many models:
module.exports = (sequelize, DataTypes) => {
const Segment = sequelize.define(
'segment',
{
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true
},
provider_id: {
type: DataTypes.INTEGER,
references: {
model: 'provider',
key: 'id'
}
},
summary_id: {
type: DataTypes.INTEGER,
references: {
model: 'summary',
key: 'id'
}
},
audience_id: {
type: DataTypes.INTEGER,
references: {
model: 'audience',
key: 'id'
}
},
onboarding_id: {
type: DataTypes.INTEGER,
references: {
model: 'onboarding',
key: 'id'
}
}
},
{
// disable the modification of table names; By default, sequelize will automatically
// transform all passed model names (first parameter of define) into plural.
// if you don't want that, set the following
freezeTableName: true,
tableName: 'segment'
}
);
Segment.associate = models => {
Segment.belongsTo(models.Provider, { foreignKey: 'id' });
Segment.belongsTo(models.Summary, { foreignKey: 'id' });
Segment.belongsTo(models.Audience, { foreignKey: 'id' });
Segment.belongsTo(models.Onboarding, { foreignKey: 'id' });
};
return Segment;
};
The models that segment has associations to (ie provider_id, summary_id, audience_id, onboarding_id) look like this:
Provider:
module.exports = (sequelize, DataTypes) => {
const Provider = sequelize.define(
'provider',
{
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true
},
providerName: {
type: DataTypes.STRING
},
email: {
type: DataTypes.STRING
},
privacyPolicy: {
type: DataTypes.STRING
}
},
{
freezeTableName: true,
tableName: 'provider'
}
);
Provider.associate = models => {
Provider.hasMany(models.Segment, { foreignKey: 'provider_id' });
};
return Provider;
};
Summary:
module.exports = (sequelize, DataTypes) => {
const Summary = sequelize.define(
'summary',
{
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true
},
summaryName: DataTypes.STRING,
standardIdName: DataTypes.STRING,
description: DataTypes.STRING,
},
{
freezeTableName: true,
tableName: 'summary'
}
);
Summary.associate = models => {
Summary.hasMany(models.Segment, { foreignKey: 'summary_id' });
};
return Summary;
};
Audience:
module.exports = (sequelize, DataTypes) => {
const Audience = sequelize.define(
'audience',
{
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true
},
refreshCadence: DataTypes.STRING,
sourceLookbackWindow: DataTypes.STRING
},
{
freezeTableName: true,
tableName: 'audience'
}
);
Audience.associate = models => {
Audience.hasMany(models.Segment, { foreignKey: 'audience_id' });
};
return Audience;
};
Onboarding:
module.exports = (sequelize, DataTypes) => {
const Onboarding = sequelize.define(
'onboarding',
{
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true
},
onboardingExpansions: DataTypes.STRING,
onboardingAudiencePrecision: DataTypes.STRING
},
{
freezeTableName: true,
tableName: 'onboarding'
}
);
Onboarding.associate = models => {
Onboarding.hasMany(models.Segment, { foreignKey: 'onboarding_id' });
};
return Onboarding;
};
My question is: what should come first when creating and saving a Segment record? Do I create and save each one of the other models first (provider, summary, audience, onboarding), and then create/save a Segment with references to those ids? I don't really know what the order of events should be in this situation. Any help is much appreciated! Thanks!
TLDR:
In order to create an instance of Segment, you must have all 4 foreign keys reference exist records on the referenced tables(provider, summary, audience and onboarding).
Explanation:
provider, summary, audience and onboarding tables are independent.
However, Segment model is not independent.
Segment model has 4 columns which are foreign keys.
From PostgresSql Tutorial:
A foreign key is a field or group of fields in a table that uniquely
identifies a row in another table. In other words, a foreign key is
defined in a table that references to the primary key of the other
table.
The table that contains the foreign key is called referencing table or
child table. And the table to which the foreign key references is
called referenced table or parent table.
It means that a foreign key is a constraint that the column should reference the primary key of the referenced table.
So, you must create all the resources of a created row of Segment.