Sequelize Not Creating a Through Table - javascript

I am trying to associate a User model and an Age model with a many to many relationship. The user and age model are being created however the through table isn't. Here is my code:
const { Sequelize, Op, QueryTypes } = require('sequelize')
const db = new Sequelize('postgres://localhost:5432/sqlstuff', {
logging: false
})
const Age = db.define('Age', { age: Sequelize.INTEGER }, { timestamps: false })
const User = db.define('User', {
firstName: Sequelize.STRING,
lastName: Sequelize.STRING,
}, { timestamps: false })
async function create() {
try {
//Both Users and Ages Table are created. Both tables are properly populated
const people = await User.bulkCreate([
{ firstName: 'Tyler', lastName: 'Kumar'},
{ firstName: 'Sabi', lastName: 'Kumar'}
], { validate: true }, { fields: ['firstName', 'lastName']})
const myAge = await Age.create({ age: 22 })
//Line 21 and 22 do not create a through table, unsure why
User.belongsToMany(Age, { through: 'UserAges' })
Age.belongsToMany(User, { through: 'UserAges' })
//Line 23 creates the error 'relation "UserAges" does not exist'
await people[1].addAge(myAge)
} catch (error) {
console.error(error)
}
}
async function connect() {
try {
await db.sync({ force: true })
await create()
await db.close()
} catch (error) {
console.error(error)
}
}
connect()

Related

Express doesn't get another user with .map()

I came to a problem, where I can create conversations with multiple people 2 and so on. However, I can't understand why it doesn't store data to seperate User models.
Here is a code that you only need to know:
router.post(
"/",
auth,
[
check("conversators", "There should be at least two conversators").isLength(
{ min: 2 }
),
],
async (req, res) => {
const { conversators } = req.body;
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
try {
let conversation = new Conversation({
user: req.user.id,
conversators: conversators,
});
await conversators.map(async (conversator) => {
let user = await User.findById(conversator);
let newData = user;
newData.conversations.push(conversation.id);
console.log('Created data', newData);
let newUser = await User.findOneAndUpdate(
{ user: conversator },
{
$set: {
newData,
},
},
{ new: true }
);
await newUser.save();
console.log(newUser);
});
await conversation.save();
res.status(200).json(conversation);
} catch (error) {
console.error(error.message);
res.status(500).send("Server error.");
}
}
);
module.exports = router;
What I can assure is that this line: console.log('Created data', newData); prints the desired data. However, the next console: console.log(newUser); prints the same User model as the previous one.
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const UserSchema = new Schema({
name: {
type: String,
required: true,
},
surname: {
type: String,
required: true,
},
email: {
type: String,
required: true,
},
password: {
type: String,
required: true,
},
conversations: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "conversation",
},
],
date: {
type: Date,
default: Date.now,
},
});
module.exports = User = mongoose.model("user", UserSchema);
The reason might be the difference in search methods used to get a record for newData and newUser. You have used User.findById for newData, which will obviously return different objects for different ids. But User.findOneAndUpdate uses filter criteria that may satisfy several results, but only first will be returned. So it boldly depends on what that user field is.
Here is the part that I changed and started to see the data on MongoDB:
await conversators.map(async (conversator) => {
let user = await User.findById(conversator);
let newData = user;
newData.conversations.push(conversation.id);
new Promise(async (resolve, reject) => {
user = await User.findOneAndUpdate(
{ id: conversator },
{
$set: {
newData,
},
},
{ new: true }
);
return resolve;
})
return await user.save();
});
Posted on behalf of the question asker

findOneandReplace keeps giving error: "Error: The replacement document must not contain atomic operators."?

I am currently developing a Pokemon Team Builder app with a React frontend and an Express backend with MongoDB for the database.
As far as I can tell my TeamSchema has no such atomic operators? Here is my TeamSchema:
const mongoose = require('mongoose');
const TeamSchema = new mongoose.Schema({
name: {
type: 'String',
required: true,
unique: true,
},
team: [
{
name: { type: String },
types: [{ type: String }],
sprite: { type: String },
},
],
username: {
type: String,
required: true,
},
userId: {
type: String,
required: true,
},
});
const TeamModel = mongoose.model('Team', TeamSchema);
module.exports = TeamModel;
And the error gets thrown in this method when I attempt to call the findOneAndReplace method by finding a team that has a name and userId match.
const replaceTeam = async (req, res) => {
const { teamName: name, filteredTeam: team } = req.body;
const { username, _id: userId } = req.user;
const newTeam = new Team({ name, team, username, userId });
try {
const replacedTeam = await Team.findOneAndReplace({ name, userId }, newTeam);
console.log(replacedTeam);
res.status(200).json({ message: 'Team was successfully overwritten!' });
} catch (err) {
console.log(err);
res.status(500).json({ message: 'An error occurred while updating the team.' });
}
};
This has been a real headscratcher here and I am not sure what is going wrong here. I have only started using mongoose a couple of weeks ago, so I wonder if it's something fundamental I am misunderstanding here.
The Mongoose function findOneAndReplace expects a document object passed in. See the below code.
details.findOneAndReplace(
{ location: "New York" },
{ name: "Sunny", age: 292, location: "Detroit" },
function(err, result) {
if (err) {
res.send(err);
} else {
res.send(result);
}
}
);
Change
const newTeam = new Team({ name, team, username, userId })
to
const newTeam = {name, team, username, userId}
Also as in the other poster's code, add the new: true option to the call as follows by changing
const replacedTeam = await Team.findOneAndReplace({ name, userId }, newTeam);
to
const replacedTeam = await Team.findOneAndReplace({ name, userId }, newTeam, { new: true });
otherwise the original document will be returned into replacedTeam
You can just use findOneAndUpdate and update all the fields with new data. You can do it like this:
const replaceTeam = async (req, res) => {
const { teamName: name, filteredTeam: team } = req.body;
const { username, _id: userId } = req.user;
try {
const replacedTeam = await Team.findOneAndUpdate({ name, userId }, { name, team, username, userId }, {new: true});
console.log(replacedTeam);
res.status(200).json({ message: 'Team was successfully overwritten!' });
} catch (err) {
console.log(err);
res.status(500).json({ message: 'An error occurred while updating the team.' });
}
};

only return _id from mongoose.find

want to fetch all users but just return list of _ids , checked the saved data in db everything seems good.
this is the user model
let UserSchema = new mongoose.Schema({
firstName: {
type: String,
minlength: 3,
trim: true,
},
lastName: {
type: String,
minlength: 3,
trim: true,
},
biography: {
type: String,
minlength: 5,
trim: true,
},
});
UserSchema.methods.toJSON = function () {
let user = this;
let userObject = user.toObject();
return _.pick(userObject, ["_id", "firstName", "email"]);
};
and this is my controller function
const controller = {
fetchUsers :async (_req, res) => {
try {
await User.find({})
.then((users) => {
res.status(200).send(users);
})
.catch((err) => {
res.status(400).send(err);
});
} catch (error) {
res.status(400).json({
Error: `something is wrong. ${error}`,
});
}
}
}
the result is that i tested in postman is :
[
{
"_id": "5fe26ba0d290a216c0fe6d5d"
},
{
"_id": "5fe26c8e40ca9a06b8c96259"
},
]
Don't use .then & await both . Try this once. Assuming model is correct.
const controller = {
fetchUsers :async (_req, res) => {
try {
const users=await User.find({}).exec()
if(users){
res.status(200).send(users);
}
else{
res.status(404).send("no user found");
};
} catch (error) {
res.status(500).json({
Error: `something is wrong. ${error}`,
});
}
}
}
problem is UserSchema.methods.toJSON method there isn't any email field, if we want to filter our output data it's better to filter it by mongoose.find({"condition"},{"fields"})

Function in async function chain not being called

I'd like to update the user's data in Firestore whenever they log in and am using the following code to do so. For some reason, the code doesn't work (see comments) and doesn't create a custom User object from firebase.User. Why is this happening/how do I fix this? I'm not getting any errors.
Code that is called to log in
async emailLogIn(email: string, password: string) {
return this.auth.signInWithEmailAndPassword(email, password)
.then( async (credential) => {
this.analytics.logEvent('logged_in', { method: 'email' });
const firebaseUser = credential.user;
if(firebaseUser) {
const user = await this.createUserFromFirebaseUser(firebaseUser);
console.log(user); // This doesn't print anything
this.updateUserData(user);
if(!firebaseUser.emailVerified) {
this.sendEmailVerification();
}
}
});
}
Code that is convert firebase.User to User (doesn't work)
async createUserFromFirebaseUser(firebaseUser: firebase.User): Promise<User> {
console.log('createUserFromFirebaseUser()');
const currentUser = await this.user.toPromise();
console.log(currentUser); // This doesn't print anything
if(currentUser)
return currentUser;
const user: User = {
uid: firebaseUser.uid,
email: firebaseUser.email,
displayName: firebaseUser.displayName,
settings: {
language: 'English',
isPrivate: false,
newFountainNotification: true,
userFountainNotification: true,
feedbackNotification: true,
units: 'Metric'
}
}
return user;
}
Getting user data from Firestore
this.user = this.auth.authState.pipe(
takeUntil(this.destroy),
switchMap( (user) => {
if(user) {
return (this.firestore.collection('users').doc(user.uid).valueChanges() as Observable<User>)
} else {
return of(null);
}
})
);
It seemed to be an issue with using this.user.toPromise()
This is the code that works:
return this.user.pipe(
take(1),
map( (currentUser) => {
if(currentUser)
return currentUser;
const user: User = {
uid: firebaseUser.uid,
email: firebaseUser.email,
displayName: firebaseUser.displayName,
settings: {
language: 'English',
isPrivate: false,
newFountainNotification: true,
userFountainNotification: true,
feedbackNotification: true,
units: 'Metric'
}
}
return user;
})
).toPromise()

How to insert multiple array objects without existing data in MongoDB with GraphQL

Current GraphQL resolver is to insert on user data. I need to insert multiple array objects to MongoDB only if the id (id != member_id) does not exist in the members database.
Datas which needs to insert
[
{
first_name: "Mate",
id: 402335654,
is_bot: false,
language_code: "ml"
}, {
first_name: "testerbot",
id: 357622799,
is_bot: false,
username: "testergroupbot"
}, {
first_name: "machan",
id: 1225612,
is_bot: false,
language_code: "ml",
username: "alavalathi"
}
]
Current resolvers
createMember: async args => {
try {
const existMember = await Member.findOne({
member_id: args.memberInput.member_id,
});
if (existMember) {
throw new Error('This user already exist');
}
const member = new Member({
member_id: args.memberInput.member_id,
first_name: args.memberInput.first_name,
last_name: args.memberInput.last_name,
username: args.memberInput.username,
date: new Date(args.memberInput.date),
});
const result = await member.save();
// eslint-disable-next-line no-underscore-dangle
return { ...result._doc };
} catch (error) {
throw error;
}
},
I am a beginner to GraphQL and MongoDB.
The solution comes with insertMany()
createMember: async args => {
try {
const newMembers = await args.memberInput.map(arg => ({
member_id: arg.member_id,
first_name: arg.first_name,
last_name: arg.last_name,
username: arg.username,
date: new Date().toISOString(),
}));
const results = await Member.insertMany(newAdmins);
return results.map(result => {
return { ...result._doc };
});
} catch (error) {
throw error;
}
},

Categories