I want to insert a new row and immediately update it, all within the same sequelize transaction, is this possible?
My code so far:
let transaction;
try {
transaction = await dbcontext.sequelize.transaction();
const newRole = await dbcontext.Role.create({
name: "New Role"
}, { transaction });
await dbcontext.Role.update(
{
name: "New name",
},
{
where: {
id: newRole.id,
},
}, { transaction }
);
await transaction.commit();
console.log("Role commited");
} catch (error) {
console.log("Rollback in progress");
if (transaction) {
await transaction.rollback();
}
console.log(error);
}
update has only two parameters so the transaction option should be indicated right next to the where option:
await dbcontext.Role.update(
{
name: "New name",
},
{
where: {
id: newRole.id,
},
transaction,
}
);
Related
// RANDOM player
"/team/:id" <= where :id represent the ObjectId of particular team
router.put("/team/:id", async (req, res) => {
try {
// This query will return random record from database (Query No. 1)
const ab = await player.aggregate([
{ $match: { selected: false } },
{ $sample: { size: 1 } },
{ $set: { selected: true } },
]);
console.log(ab, "AB");
const x = ab[0]["_id"].toString();
console.log(x, "x");
res.send(ab);
const id = req.params.id;
console.log(id);
//Push One player to the team (Query No. 2)
const insertPlayer = await team
.findByIdAndUpdate(id, { $push: { player: x } }, { new: true })
.populate("player");
console.log(insertPlayer);
res.status(201).send(insertPlayer);
// let results = await Promise.all([ab, insertPlayer]); //some more awaits below this point
} catch (error) {
console.log(error);
}
});
---------------------------------------------------------------
desired Output =>
{
"_id": "635fa8ceb3f095c16f6d2fea",
"player": [
{
"_id": "635f73ba46b7b66a966720e6",
"player_name": "Xyz",
"gender": "M",
"selected": false,
"__v": 0
}
],
"team_name": "a",
"__v": 0
},
My desired Output is need to execute first await function after that the result of that function use as the id for next await function which is team.findByIdAndUpdate().
task => team selection with random players from player collection, if any player will selected in any team then he/she cannot be selected for other team.
Try to change your logic like this:
router.put('/team/:id', async (req, res) => {
try {
// This query will return random record from database (Query No. 1)
const players = await player.aggregate([
{ $match: { selected: false } },
{ $sample: { size: 1 } },
{ $set: { selected: true } },
]);
if (players.length === 0) {
return res.status(400).send('No players found');
}
const id = req.params.id;
const player = players[0];
const insertPlayer = await team
.findByIdAndUpdate(id, { $push: { player: player._id } }, { new: true })
.populate('player')
.exec();
res.status(201).send(insertPlayer);
} catch (error) {
res.status(500).send('Server error');
}
});
I am learning mongoose and I'm unable to understand some code execution order of javascript
Code:
const mongoose = require("mongoose");
mongoose.connect("mongodb://localhost:27017/fruitsDB");
const fruitSchema = new mongoose.Schema({
name: {
type: String,
required: [true, "Please check your data entry, no name specified!"],
},
rating: {
type: Number,
min: 1,
max: 10,
},
review: String,
});
const Fruit = mongoose.model("Fruit", fruitSchema);
// Reading data from database
Fruit.find((err, fruits) => {
if (err) {
console.log(err);
} else {
// console.log(fruits);
mongoose.connection.close();
fruits.forEach((fruit) => {
console.log(fruit.name);
});
}
});
// Updating data in database
Fruit.updateOne({ name: "Kiwi" }, { name: "Peach" }, (err) => {
if (err) {
console.log(err);
}
else {
console.log("Successfully updated data");
}
});
// Deleting data in database
Fruit.deleteOne({ name: 'Peach' }, (err) => {
if (err) {
console.log(err);
}
else {
console.log('Data deleted successfully');
}
})
console.log output:
I am unable to understand why the Update function in running before the find() function, can anyone explain this to me please?
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()
I now have a code that works.
await Users.update({ selected: false }, { where: { userId: req.body.userId } });
await Users.update(
{
selected: req.body.selected,
descr: req.body.note
},
{
where:
{
entId: req.body.id,
userId: req.body.userId
}
}
);
But what if it is possible to combine these two queries into one? I need the 'selected' and 'note' field that I pass to change conditionally in the table. And all other 'selected' fields inherent to the user in the table became false.
Unfortunately, I did not find anything like that in the documentation. Thank you in advance for your help!
Unfortunately there is no such method like bulkUpdate in Sequelize so you need to call update twice and better to use a transaction to make these two queries as a one atomic operation.
await Sequelize.transaction(async transaction => {
await Users.update({ selected: false }, { where: { userId: req.body.userId }, transaction });
await Users.update(
{
selected: req.body.selected,
descr: req.body.note
},
{
where:
{
entId: req.body.id,
userId: req.body.userId
},
transaction
}
);
});
You can use the sequelize transaction and wrap it up inside try/catch,
// define transaction outside the try/catch so you can rollback if needed
const transaction = await sequelize.transaction();
try {
await Users.update({ selected: false }, { where: { userId: req.body.userId }, transaction })
.then((r) => r)
.catch((e) => {
throw e;
});
await Users.update(
{
selected: req.body.selected,
descr: req.body.note
},
{
where: {
entId: req.body.id,
userId: req.body.userId
},
transaction
}
)
.then((r) => r)
.catch((e) => {
throw e;
});
// always call commit at the end
await transaction.commit();
return true;
} catch (error) {
// always rollback
await transaction.rollback();
console.log(error);
throw error;
}
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;
}
},