Sequelize .set error, .set is not a function - javascript

I am trying to set up a belongsTo and hasMany association which seems to be working, but when I run .set I am getting the error fighterData.setUsers is not a function. The dialect is mySql. Here is my code:
Fighters.belongsTo(Users)
Users.hasMany(Fighters);
Users.sync()
Fighters.sync()
//creates the table if it doesn't exist
const insertFighter = function(obj, sessId) {
return Fighters.create(obj, {returning: true}).then((fighterData) => {
//console.log('inserted a fighter \n', fighterData);
return Users.findOne({
where: {
id: sessId
}
}).then((userData) => {
//console.log('fighterData in findOne promise \n', fighterData)
return fighterData.setUsers(userData)
}).then((success)=> {
console.log('user fighter join success')
return
}).catch((err)=> {
console.log('user fighter join error \n', err)
return
})
}).catch((err)=> {
console.log('error inserting fighter \n', err);
})
}
The error that's logging is user fighter join error.
interestingly, userData.setFighters(fighterData) works successfully, but that is not what I need
EDIT
This is what fighterData is:
fighterData in findOne promise
Fighters {
dataValues:
{ id: 7,
name: 'Gilbert Burns',
image:
'https://www.sherdog.com/image_crop/200/300/_images/fighter/20140806063215_IMG_8432.JPG',
next_opponent: 'Kamaru Usman',
next_fight: 'July 11, 2020 ',
style: 'mma',
updatedAt: 2020-06-17T06:00:40.368Z,
createdAt: 2020-06-17T06:00:40.368Z },
_previousDataValues:
{ name: 'Gilbert Burns',
image:
'https://www.sherdog.com/image_crop/200/300/_images/fighter/20140806063215_IMG_8432.JPG',
next_opponent: 'Kamaru Usman',
next_fight: 'July 11, 2020 ',
style: 'mma',
id: 7,
createdAt: 2020-06-17T06:00:40.368Z,
updatedAt: 2020-06-17T06:00:40.368Z,
UserId: undefined },
_changed:
{ name: false,
image: false,
next_opponent: false,
next_fight: false,
style: false,
id: false,
createdAt: false,
updatedAt: false,
UserId: false },
_modelOptions:
{ timestamps: true,
validate: {},
freezeTableName: false,
underscored: false,
paranoid: false,
rejectOnEmpty: false,
whereCollection: null,
schema: null,
schemaDelimiter: '',
defaultScope: {},
scopes: {},
indexes: [],
name: { plural: 'Fighters', singular: 'Fighter' },
omitNull: false,
sequelize:
Sequelize {
options: [Object],
config: [Object],
dialect: [MysqlDialect],
queryInterface: [QueryInterface],
models: [Object],
modelManager: [ModelManager],
connectionManager: [ConnectionManager],
importCache: {} },
hooks: {} },
_options:
{ isNewRecord: true,
_schema: null,
_schemaDelimiter: '',
attributes: undefined,
include: undefined,
raw: undefined,
silent: undefined },
isNewRecord: false }
This is returned from entering one fighter's information into the database.

The problem is with the naming of your models.
Sequelize expects your models to be named in singular form (User instead of Users), so it's getting confused with what it should name the generated setter and getter methods for your association.
If you try fighterData.setUser(userData) instead of fighterData.setUsers(userData), it should work.
If you you want to use setUsers instead, you will have to make adjustments to your model to tell Sequelize to use Users as the singular form of User:
Users.init({
sessId: Sequelize.STRING
}, {
sequelize: sequelize,
name: {
singular: 'users'
}
});
You can overwrite the plural form the same way as well.
You can read more about this here: Sequelize naming strategy

Related

Sequelize - Build dynamic where clause with 'Op.or'

I had this code block working with Sequelize v5. But since switching to v6, it seems to be erroring out. I am getting the error: Error: Invalid value { customer_id: 'dg5j5435r4gfd' }.
And here is the code that creates the where condition block:
let whereBlock = {
deleted_at: null,
};
if (args.includeCore) {
if (customerID !== 'all') {
// whereBlock[Op.or] = [
// { customer_id: customerID },
// { customer_id: coreCustomerID },
// ];
whereBlock[Op.or] = [];
whereBlock[Op.or].push({
customer_id: customerID,
});
whereBlock[Op.or].push({ customer_id: coreCustomerID });
}
} else {
whereBlock.customer_id = customerID;
}
I was using the commented code. And then I tried the code below that. Both are producing the same error. But when I remove all that code from the if block and just put in whereBlock.customer_id = customerID;, then it works fine. So I know the issue is how I am constructing the where condition.
Update: As requested, here is my Sheets model where the where clause is being run on.
'use strict';
export default (sequelize, DataTypes) => {
return sequelize.define(
'Sheet',
{
id: {
type: DataTypes.UUID,
primaryKey: true,
defaultValue: DataTypes.UUIDV4,
},
sheet_name: {
type: DataTypes.STRING,
isAlphaNumeric: true,
required: true,
allowNull: true,
len: [3, 80],
},
sheet_file_name: {
type: DataTypes.STRING,
unique: true,
isAlphaNumeric: true,
required: false,
allowNull: true,
},
brand_name: {
type: DataTypes.STRING,
unique: false,
isAlphaNumeric: true,
required: false,
allowNull: true,
},
customer_id: {
// fk in customers table
type: DataTypes.TINYINT(2).UNSIGNED,
required: true,
allowNull: false,
},
chemical_id: {
// fk in loads table
type: DataTypes.SMALLINT.UNSIGNED,
required: true,
allowNull: false,
},
load_id: {
// fk in loads table
type: DataTypes.SMALLINT.UNSIGNED,
required: true,
allowNull: false,
},
active: {
type: DataTypes.BOOLEAN,
required: true,
allowNull: false,
defaultValue: true,
},
created_at: {
type: DataTypes.DATE,
},
updated_at: {
type: DataTypes.DATE,
},
deleted_at: {
type: DataTypes.DATE,
},
},
{
underscored: true,
paranoid: false,
}
);
};
And in my index I have this to associate sheets with customers: db.Sheet.belongsTo(db.Customer);
Also here is the full code where the whereBlock is used, if that helps:
const files = await db.Sheet.findAll({
raw: true,
attributes: [
'sheet_name',
'sheet_file_name',
['brand_name', 'brand'],
'updated_at',
'active',
[Sequelize.col('Chemical.name'), 'chemical'],
[Sequelize.col('Load.value'), 'load'],
],
include: [
{
model: db.Load.scope(null),
required: true,
as: 'Load',
attributes: ['value'],
},
{
model: db.Chemical.scope(null),
required: true,
as: 'Chemical',
attributes: ['name'],
},
],
// model: model,
where: whereBlock,
order: [['active', 'DESC']],
});
TLDR: So here is what it comes down to:
whereBlock = {
deleted_at: null,
customer_id: customerID,
// [Op.or]: [
// { customer_id: customerID },
// { customer_id: coreCustomerID },
// ],
};
That code above works, but the commented code errors out with: Error: Invalid value { customer_id: '123456' }
OK, this is very weird. But I finally figured out the issue!! Was not something I would have thought of, just found it by chance. It was the way I was importing Op from sequelize.
import Op from 'sequelize';
So apparently, that Op object has another object inside it called Op. So when I call my [Op.or], I instead need to do this: [Op.Op.or].
I did try switching my import to import Op.Op from 'sequelize'; and that caused errors. Anyone know how I can properly import the inner object?
Update
OK, so apparently in my other DB files, I was doing the import differently.
export default (db) => {
const Op = db.Sequelize.Op;
That method works to pull in the correct Op object. So there you go. Hopefully this nightmare issue helps someone else in the future.

Unable to update record in MongoDB using findOneAndUpdate

I am using Mongoose to update an Announcement record, with the following definition:
const { DateTime } = require('luxon');
const Schema = new mongoose.Schema({
title: String,
description: String,
date: {
type: Date,
set: (dt) => dt.toJSDate(),
get: (d) => DateTime.fromJSDate(d),
},
club: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Club',
},
});
I am performing the update operation in this function
exports.update = async (id, params) => {
console.log(params)
await Announcement.findOneAndUpdate({ _id: id }, params, {
upsert: true,
useFindAndModify: false,
});
return "exports.get(id)";
};
However, I get an error when running Announcement.findOneAndUpdate:
$set' is empty. You must specify a field like so: {$set: {<field>: ...}}
This is what the params look like:
{
title: 'Name!',
description: 'Description!',
date: DateTime {
ts: 1601524800000,
_zone: LocalZone {},
loc: Locale {
locale: 'en-US',
numberingSystem: null,
outputCalendar: null,
intl: 'en-US',
weekdaysCache: [Object],
monthsCache: [Object],
meridiemCache: null,
eraCache: {},
specifiedLocale: null,
fastNumbersCached: null
},
invalid: null,
weekData: null,
c: {
year: 2020,
month: 10,
day: 1,
hour: 0,
minute: 0,
second: 0,
millisecond: 0
},
o: -240,
isLuxonDateTime: true
},
club: '99cb91bdc3464f14678934ca'
}
I know that all the ObjectId's are valid because I have tested them from Mongo shell. However, I can't figure out why I am not able to run findOneAndUpdate on an Announcement record.

Node.js caught error undefined but defined

I have been working on a bot for 12 days now and I need to upgrade to v12. Everything was going smoothly until I tried a command that will give a specified role to a mentioned user.
I have 2 variables. One is a role variable that the user has specified and the member variable (which is equaled to message.guild.members.get(args[0])).
The code looks like this:
let Member = message.mentions.members.first() || message.guild.members.get(arguments[0]);
if (!Member) return message.channel.send("Error: Either the member does not exist or you haven't put the member to give the role to!");
let role = message.guild.roles.cache.some(r => r.name === arguments[1]) || message.guild.roles.cache.some(r => r.id === arguments[1]) || message.mentions.roles.first();
if (!role) return nessage.channel.send("Error: Please provide a valid role!");
// if (role === "undefined") {
// let role = message.guild.roles.cache.some(r => r.name === arguments[1]) || message.guild.roles.cache.some(r => r.id === arguments[1]) || message.mentions.roles.first();
// }
if (Member.roles.cache.has(role.id)) {
return message.channel.send("Error: The mentioned user already has that role!");
} else {
let role = message.guild.roles.cache.some(r => r.name === arguments[1]) || message.guild.roles.cache.some(r => r.id === arguments[1]) || message.mentions.roles.first();
console.log(message);
console.log("role" + role);
Member.roles.add(role.id).catch(e => console.log("Error: " + e.message));
}
The code looked fine to me and expected it to work, but then I got an error in the console. It doesn't say what variable is not defined, it just says it's undefined.
I tried checking if the role variable is undefined, but I commented out since it didn't work. Then, I have let it print the message and check if the role is undefined. The role variable is fine. The message variable is fine. Even the Member variable is fine.
I use the latest Node.js.
Here's the console log:
Message {
channel: TextChannel {
type: 'text',
deleted: false,
id: '729663938148565134',
name: 'general',
rawPosition: 0,
parentID: '729663938148565132',
permissionOverwrites: Collection [Map] {},
topic: 'Beware, there will be a lot of mentions.',
nsfw: undefined,
lastMessageID: '733951355240316948',
rateLimitPerUser: 0,
lastPinTimestamp: 1594845448699,
guild: Guild {
members: [GuildMemberManager],
channels: [GuildChannelManager],
roles: [RoleManager],
presences: [PresenceManager],
voiceStates: [VoiceStateManager],
deleted: false,
available: true,
id: '729663937557168181',
shardID: 0,
name: 'Bot Testing',
icon: null,
splash: null,
region: 'europe',
memberCount: 6,
large: false,
features: [],
applicationID: null,
afkTimeout: 300,
afkChannelID: null,
systemChannelID: '729663938148565134',
embedEnabled: undefined,
premiumTier: 0,
premiumSubscriptionCount: 0,
verificationLevel: 'MEDIUM',
explicitContentFilter: 'DISABLED',
mfaLevel: 0,
joinedTimestamp: 1594035922599,
defaultMessageNotifications: 'ALL',
systemChannelFlags: [SystemChannelFlags],
vanityURLCode: null,
description: null,
banner: null,
rulesChannelID: null,
publicUpdatesChannelID: null,
ownerID: '402159567200583680',
emojis: [GuildEmojiManager]
},
messages: MessageManager {
cacheType: [Function: LimitedCollection],
cache: [LimitedCollection [Map]],
channel: [Circular]
},
_typing: Map { '402159567200583680' => [Object] }
},
deleted: false,
id: '733951355240316948',
type: 'DEFAULT',
content: '>giveRole <#!655895332722442282> Mod',
author: User {
id: '402159567200583680',
bot: false,
username: '🎁🎄KFM🎄🎁',
discriminator: '3147',
avatar: '5f322e4ab3ec14e9fa83e1c77d8bb36d',
lastMessageID: '733951355240316948',
lastMessageChannelID: '729663938148565134',
flags: UserFlags { bitfield: 0 }
},
pinned: false,
tts: false,
nonce: '733951341017169920',
system: false,
embeds: [],
attachments: Collection [Map] {},
createdTimestamp: 1595058039246,
editedTimestamp: null,
reactions: ReactionManager {
cacheType: [Function: Collection],
cache: Collection [Map] {},
message: [Circular]
},
mentions: MessageMentions {
everyone: false,
users: Collection [Map] { '655895332722442282' => [User] },
roles: Collection [Map] {},
_members: Collection [Map] { '655895332722442282' => [GuildMember] },
_channels: null,
crosspostedChannels: Collection [Map] {}
},
webhookID: null,
application: null,
activity: null,
_edits: [],
flags: MessageFlags { bitfield: 0 },
reference: null
}
roletrue
Error: undefined
Thanks in advance!
EDIT: It looks like the role.id is undefined. I will try to see how to fix that.
I think problem with this part of code
console.log("role" + role); // true
Member.roles.add(role.id).catch(e => console.log("Error: " + e.message));
You trying add undefined in roles, because:
const roleId = (true).id;
console.log(roleId); //undefined
Your got your Boolean from some function which always return true or false, try change this to find
try add some id like 733951355240316948.
I dont know how looks role.id, but role must be Object
for example:
{
id:'asdasdawe3534536456',
// other fields
}
You need find what expect .add function in Member.roles.add

Why are mongoose query result objects so verbose in new version?

I installed my dependencies on a new computer and it must have updated mongoose.
All my informative results from queries have returned into these messes with a lot of information that may be useful at times but generally is not useful. Very verbose.
So for example when it runs console.log(result) in a query promise, it used to return something like this:
user: {
_id: '2c918aa5-3d5f-4397-8dd9-35c3675f53a2',
email: 'ayeman#gmail.com',
username: 'ayeman',
password: '$2b$10$1sBah/12s12Ox0971221nk5g2s12s11FVRCW',
watching: '',
__v: 0
}
instead now it returns this:
model {
'$__': InternalCache {
strictMode: true,
selected: {},
shardval: undefined,
.....
*200 plus lines of verbose data*
....
remove: [Function: pull],
_path: 'chats',
isMongooseArray: true,
validators: [],
_schema: [SchemaArray]
],
_id: '2c918aa5-3d5f-4397-8dd9-35c3675f53a2',
email: 'ayeman#gmail.com',
username: 'ayeman',
password: '$2b$10$1sBah/12s12Ox0971221nk5g2s12s11FVRCW',
watching: '',
__v: 0
},
'$init': true
}
I cant for the life of me find the documentation to return it to the old style.
It seems silly to find all my console logs and cut the extra data manually.
Is there a method to change this back? I was looking for something like mongoose.model.options.changeResultsStyle() or something but I cannot find anything
In the new mongoose version it seems as if it defaults to verbose results. Using .lean() on mongoose query methods will return the lean style that the old mongoose version defaulted too.
My example scenario
User.findOne({username: req.body.username }, {friends: 1}, function(err, result) {
if (err) throw err;
console.log(result.friends[1].pending)
res.json(result.friends[1].pending);
}).lean();
{
_id: '2c918aa5-3d5f-4397-8dd9-35c3675f53a2',
friends: [ { confirmed: [Array] }, { pending: [Array] } ],
status: 'offline',
chats: [ { confirmed: [Array] }, { pending: [Array] } ],
email: 'ayeman#gmail.com',
username: 'ayeman',
password: '$2b$10$gq0OrbxulaUBah/O.LhfjuiOx0970brivNStLXnk5gGn0QYRFVRCW',
watching: '',
__v: 0
}

Using Object.assign() on a doc returned from a mongoose Model query

When using Object.assign() on a document returned from a mongoose model query, the object returns extraneous data which I do not want, and to get the actual document data I need to use doc._doc - whereas without using Object.assign() I have immediate access to the document data (not inside ._doc).
UserModel.findOne(query, function(err, doc){
//this outputs my document data just fine
console.log(doc);
//this outputs extraneous data, assigning someProp not to my document data,
//but to the outer object.
console.log(Object.assign({}, doc, { someProp: true});
})
Here is the result of console.log(doc):
{
_id: 5ab5df214869bc4bfc059fed,
userID: 0,
verified: false,
verificationCode: 'vC_10a89847-f640-43fc-94cc-8ea532f5e05c',
email: 'ee#ee.ee',
createdAt: 2018-03-24T05:16:17.508Z,
updatedAt: 2018-03-25T16:57:30.101Z,
__v: 0
}
And here is the result of console.log(Object.assign({}, doc, { someProp: true });
{ '$__':
InternalCache {
strictMode: true,
selected: {},
shardval: undefined,
saveError: undefined,
validationError: undefined,
adhocPaths: undefined,
removing: undefined,
inserting: undefined,
version: undefined,
getters: {},
_id: 5ab5df214869bc4bfc059fed,
populate: undefined,
populated: undefined,
wasPopulated: false,
scope: undefined,
activePaths: StateMachine { paths: [Object], states: [Object], stateNames: [Array] },
pathsToScopes: {},
ownerDocument: undefined,
fullPath: undefined,
emitter: EventEmitter { domain: null, _events: {}, _eventsCount: 0, _maxListeners: 0 },
'$options': true },
isNew: false,
errors: undefined,
_doc:
{
_id: 5ab5df214869bc4bfc059fed,
userID: 0,
verified: false,
verificationCode: 'vC_10a89847-f640-43fc-94cc-8ea532f5e05c',
email: 'ee#ee.ee',
createdAt: 2018-03-24T05:16:17.508Z,
updatedAt: 2018-03-25T16:57:30.101Z,
__v: 0 },
'$init': true,
someProp: true }
My question is, why do I need to use doc._doc inside and after using doc = Object.assign({}, doc._doc, { someProp: true }) to access my document data, but I could access the data properties without ._doc before using doc = Object.assign(...)?

Categories