So when I query without attribute: exclude... it returns me the correct user, but when I insert that in the query it returns a completly different user. Here is the code that I'm inserting.
const user = await Users.findOne(
{
attributes: { exclude: ["password", "admin", "createdAt", "updatedAt"] },
},
{ where: { id: req.user.id } }
);
res.json({ user });
Any ideas why is this happening?
Thanks in advance
You'r passing the where condition to the second paramter, but according to the docs: https://sequelize.org/docs/v6/core-concepts/model-querying-finders/#findone
Model.findOne only has one parameter which is the query options.
Move your where condition into the object for the first parameter.
const user = await Users.findOne({
attributes: {
exclude: ["password", "admin", "createdAt", "updatedAt"],
},
where: { id: req.user.id },
});
res.json({ user });
I've been trying to automate the creation of my sequelize models by creating them with a generic model that I can pass definitions into, rather than creating a model file specifically for each one.
I have an array of model definitions which looks something like this:
const modelDefinitions = [
{
name: "User",
fieldDefinitions: [
{
name: "first_name",
label: "First Name",
column_type: Sequelize.DataTypes.STRING,
},
{
name: "last_name",
label: "Last Name",
column_type: Sequelize.DataTypes.STRING,
},
{
name: "email",
label: "Email",
column_type: Sequelize.DataTypes.STRING,
},
{
name: "password",
label: "Password",
restricted: true,
column_type: Sequelize.DataTypes.STRING,
},
],
},
{
name: "Audit",
fieldDefinitions: [
{
name: "ref",
column_type: Sequelize.DataTypes.STRING,
label: "Audit Ref",
},
{
name: "result",
column_type: Sequelize.DataTypes.STRING,
label: "Result",
},
{
name: "auditor_id",
column_type: Sequelize.DataTypes.INTEGER,
label: "Auditor",
},
],
},
];
When my array of models contains just one model it works perfectly fine, but when I have multiple, the GenericModel of the previously defined models is then "changed" to ne the last one in the list that was initialised.
I'm new to node so I think I'm either missing something or there's some sort of model caching happening, meaning that all instances of GenericModel become what it is initialised as last.
Please see my example below (the commented out code is what I used to use to define the models and the reduce is my new way of defining these)
// {
// User: User.init(sequelize, modelDef),
// Article: Article.init(sequelize, modelDef),
// Audit: Audit.init(sequelize, modelDef),
// Form: Form.init(sequelize, modelDef),
// };
const models = modelDefinitions.reduce((acc, modelDef) => {
return { ...acc, [modelDef.name]: GenericModel.init(sequelize, modelDef) };
}, {});
console.log({ models });
My console.log() returns the following - notice both are Group :
{
models: {
User: Group,
Group: Group
}
}
As you can see, what ever the last model is defined as, the previous ones inherit that instead of keeping what I defined them as originally.
But what I actually want is :
{
models: {
User: User,
Group: Group
}
}
If my list only had User in it, it works fine.
I managed to get this working in the end.
I think my issue was that my GenericModel was treated as a Singleton, so to get around this I changed GenericModel from extending the Sequelize.Model and instead made a new class with a contructor to consume my arguments and then created a method on the new class to return the sequelize model.
The main change there was instead of defining the models with GenericModel.init(), I defined them by calling sequelize.define(modelName, attributes, options)
so my map now looks like this :
const models = modelDefinitions.reduce((acc, modelDef) => {
return { ...acc, [modelDef.name]: new GenericModel(sequelize, modelDef).getDBModel() };
}, {});
and my class:
class TestModel {
constructor(sequelize, modelDef) {
this.sequelize = sequelize;
this.modelDef = modelDef;
this.modelName = modelDef?.name;
this.definitions = modelDef?.fieldDefinitions;
this.restrictedFieldList = this.definitions.filter((field) => field?.restricted).map((definition) => definition.name);
}
getDBModel() {
const model = this.sequelize.define(
this.modelName,
this.definitions.reduce((acc, definition) => {
return { ...acc, [definition.name]: definition.column_type };
}, {}),
{
defaultScope: {
attributes: {
exclude: this.restrictedFieldList,
},
},
sequelize: this.sequelize,
modelName: this.modelName,
}
);
return model;
}
}```
I have an association on a self referencing table which requires an alias.
I'm currently trying to query the table twice. However I'm running into a
Transaction (OneTimeDebits) is not associated to Transaction! error.
It seems that since the self referencing association requires an alias there is no way to query the association with a different alias.
Is there some way I can get around this?
models.Transaction.hasMany(models.Transaction, { as: 'Debits', foreignKey: 'PaymentId' });
models.Transaction.belongsTo(models.Transaction, { as: 'Payment', foreignKey: 'PaymentId' });
models.Transaction.findAll({
where: {
'$OneTimeDebits.id$': null,
},
include: [{
model: models.Transaction,
where: {
OneTime: true,
},
required: false,
as: 'OneTimeDebits',
},
{
model: models.Transaction,
where: {
FinalDebit: true,
},
as: 'FinalDebits',
}],
});
I have a table named person, I want a column to be excluded as default,
const Person = sequelize.define('person',{
secretColumn: Sequelize.STRING,
//... and other columns
});
I see that there is a feature called Scope in Sequelize:
http://docs.sequelizejs.com/manual/tutorial/scopes.html
I tried to exclude like this;
const Person = sequelize.define('person',{
secretColumn: Sequelize.STRING,
//... and other columns
}, {
defaultScope: {
exclude: ['secretColumn']
}
});
But that does't work. Is there any other way to exclude a column by default?
I firgured it out. exclude needs to be in attributes part:
const Person = sequelize.define('person',{
secretColumn: Sequelize.STRING,
//... and other columns
}, {
defaultScope: {
attributes: { exclude: ['secretColumn'] }
}
});
I have two loopback models: user and backendUser. One (user) is stored with loopback and the other one (backendUser) is stored on a distant mysql database. They have a relation togerther based on a field user has (backendUserId) corresponding to the ID field of backendUser
There is a case where I get every user with its corresponding backendUser. But I would like to get the users depending on some backendUser values. Example: I need every user where the backendUser.role is 4.
I use this filter to have the expected result:
{ include: { relation: "backendUser", scope: { where: { "role" : 4 } } } }
My issue is that I get an array of every user but I only get related backendUser when they have role to 4. The where is only applying on backendUser not on the whole entity.
I don't know if it's clear, but I really need this.
Use the following:
{
where: {
role: 4,
include: {
relation: "backendUser",
scope: {
where: { "role": 4 }
}
}
}
}
{
where: {
// here specific object of query user
},
include: [
{
relation: 'backendUser',
scope: {
where: {
role: 4,
},
},
},
],
}