Updating a nested objects in Mongoose - node.js

I have the following express route:
const updateSnapshot = async (req, res) => {
const accountId = req.body.account_id;
if (!accountId) {
return fail(res, 'account id is missing', 400);
}
try {
const account = await Account
.findOne({ _id: accountId})
.populate({
path: 'snapshot',
model: 'Snapshot'
});
// I want to update these fields in snapshot
const snapshot = {
friends_count: data.friends_count,
updated_date: new Date()
};
account.snapshot.friends_count = snapshot.friends_count;
account.snapshot.updated_date = snapshot.updated_date;
await account.save();
return success(res, snapshot);
} catch(error) {
fail(res, error.message, 500);
}
};
I want to update the nested object snapshot (just the fields friends_count and update_date) however when I check the database it seems to have not work. What am I doing wrong here?

const updateSnapshot = (req, res) => {
const accountId = req.body.account_id;
if (!accountId) {
return fail(res, 'account id is missing', 400);
};
Account
.findOneAndUpdate({ _id: accountId }, {
$set: {
snapshot: {
friends_count: data.friends_count,
updated_date: new Date()
}
}
}, {
new: true
})
.then(account => {
if(!account) {
return fail(res, "Account not found", 404);
} else {
return success(res, account);
};
})
.catch(err => {
return fail(res, error.message, 500);
});
};
Here we're using the findOneAndUpdate method and promises to find and update the document in one operation.
findOneAndUpdate takes the query criteria as the first parameter, the second parameter updates values specified in the object (we're using the $set operator to update specific values of the snapshot object), and the three parameter is an object that defines the operation's options (new is set to true to return the newly updated object).
Note: $set will replace the entire snapshot object so if there are other properties inside the snapshot object, they will need to be included inside the $set object.

Related

how to unset (delete) field in findByIdAndUpdate in mongoDB

I have an API that update a post and I want when a field is passed as undefined to delete this field or at least set it to undefined.
Here is my current implementation but it's not working:
const finalData = {
_id,
...,
mileage,
};
const result = await provider.updatePost(finalData);
and my provider
updatePost: async (payload) => {
const { _id, ...newData } = payload;
const result = await Model.findByIdAndUpdate(_id, newData, {
new: true,
omitUndefined: true,
});
await indexPost(result);
if (!result) {
throw new NotFound('No post found');
}
return result;
}

I want to delete all the item but except of the current user

I am creating a call that deletes all the users except the current user logged in.
Here is my code;
exports.deletealluser = async (req, res) => {
try {
const { sub } = req.user;
const usersExceptCurrent = await User.find({ _id: !sub });
const deletedUsers = await User.deleteMany(usersExceptCurrent);
res.status(201).json({
message: 'A all user is successfully deleted!',
deletedUsers,
});
} catch (err) {
return res.status(400).json({
message: 'Something went wrong.',
});
}
};
sub is the id of the current user. As you can see, I call find query first to filter the data which is not equal to sub. Then I use the usersExceptCurrent as filter to my deleteMany query.
But it returns status 400
And here is my axios call;
const onDelete = async () => {
try {
const { data } = await fetchContext.authAxios.delete(
'admin/delete-all-users'
);
fetchContext.setUserList(
fetchContext.userList.filter((row) => row === data.deletedUsers)
);
setSignupSuccess(data.message);
setSignupError('');
setOpen(false);
setOpenAlert(false);
} catch (err) {
setIsLoaded(true);
setError(err);
const { data } = err.response;
setSignupError(data.message);
setSignupSuccess('');
}
};
Use $ne
$ne selects the documents where the value of the field is not equal to the specified value. This includes documents that do not contain the field.
db.collection.find({ _id: { $ne: sub } })
Demo - https://mongoplayground.net/p/ecMNn4ueZrn
If you still face for _id should be ObjectId you can do
const ObjectId = require("mongodb").ObjectId;
db.collection.find({ _id: { $ne: ObjectId(sub) } })
See what ! does, converts to bool value in JS
console.log(!"a");
console.log(!2);

Sequelize how to get all data if there is no query string passed

I'm pretty new to Sequelize.
I'm trying to create a handler to get all playlists in my database.
This is what I want to do:
If there is a query string then it should return the result based on that query.
If there is no query string passed then it should return all my playlists.
This is my playlist model:
const Playlist = db.define("playlist", {
id: {
type: Sequelize.INTEGER,
autoIncrement: true,
primaryKey: true,
},
name: {
type: Sequelize.STRING,
unique: true,
},
});
Here is my handler:
exports.getPlaylists = async (req, res) => {
try {
const { name } = req.query;
console.log(name); // this prints the name
const result = await Playlist.findAll({
where: {
name:
name === undefined ? {} : { $like: `%${name}%` },
},
});
if (result) {
res.status(200).send(result);
} else {
response.status(404).send("No Playlists found");
}
} catch (error) {
res.status(500).send(`Internal server error: ${error}`);
}
};
This works well if I passed a name in the query. but If I didn't pass any query string. It returns an empty array.
$like is an alias for Sequelize.Op.like
What should I put instead of the empty object?
I checked this question How get all data if field in query string is empty Node and Sequelize with Postgres but the proposed solutions didn't work with me
Create a filter object based on the condition. If you pass empty object to where, it won't apply that in the query.
exports.getPlaylists = async (req, res) => {
try {
const { name } = req.query;
const filters = {};
if (name)
filters.name = {
[Op.like]: `${name}%`, // you can also use $like if you are using older version of sequelize
}
const result = await Playlist.findAll({
where: filters,
});
if (result) {
res.status(200).send(result);
} else {
response.status(404).send("No Playlists found");
}
} catch (error) {
res.status(500).send(`Internal server error: ${error}`);
}
};
This way you can prepare complex filters based on other query strings.

When I make db process inside async map function, I can't avoid duplicate

I want to add pallet barcode to palletBarcodes field of record.But there is check for avoid add same palletBarcode.I am using below function. But check is not working inside async map function.
myService.js
const palletBarcodes = ["TP2","TP2"]
await Promise.all(palletBarcodes.map(async (palletBarcode) => {
const promise = await this.addPalletBarcode({ transferId, barcode: palletBarcode });
return promise;
}));
async addPalletBarcode({ transferId, barcode, pickerId }) {
const { TransferDataAccess } = this;
const transfer = await TransferDataAccess.getTransfer({ transferId });
if (!transfer) {
throw new TransferNotFoundError();
}
if (transfer.palletBarcodes.length && transfer.palletBarcodes.includes(barcode)) {
throw new PalletBarcodeAlreadyExistsError({ barcode });
}
return TransferDataAccess.pushPalletBarcode({ transferId, barcode });
}
transferDataAccess:
async pushPalletBarcode({ transferId, barcode }) {
const { TransferModel } = this;
return TransferModel
.findOneAndUpdate({
_id: transferId,
},
{
$push: {
palletBarcodes: barcode,
},
})
.lean()
.exec();
}
Instead of $push use $addToSet. $addToSet will treat your key in document as a set and that will automatically avoid duplicates.
You query would then become -
TransferModel.findOneAndUpdate(
{ _id: transferId },
{ $addToSet: { palletBarcodes: barcode } }
);

node mongoose updating an Object in Array doesn't work

I am trying to update an Array of objects wo any success..
the update statement does not work ..
I may have to update the table instance array and update it with the new valueand then save the table...
const picked = table.meta.permissions.find(obj => obj._id == req.params.permissionId);
console.log('picked: %j', picked); // need to update it !
// how can I update this permission object with the new value from req.body ?
table.save()
.then(savedTable => res.json(savedTable))
.catch(e => next(e););
I have an Array of permissions in a 'meta' field:
MODEL
const Schema = mongoose.Schema;
const Permission = new Schema({
permission: {
role_id: { type: String },
canWrite: { type: Boolean }
}
});
const TableSchema = new mongoose.Schema({
meta: {
name: { type: String, required: true },
permissions: [Permission],
...
},
...
);
In the controller , I firstly load the requested table and append it to the req object, then I execute the updatePermission function, and try to update the table instance permission with new values using $set
CONTROLLER
import Table from '../../models/table.model';
/**
* Load table and append to req.
*/
function load(req, res, next, id) {
Table.get(id)
.then((table) => {
req.table = table;
return next();
})
.catch(e => next(e));
}
function updatePermission(req, res, next) {
const table = req.table;
console.log('Current table.meta.permissions: %j', table.meta.permissions, '\n');
console.log('update permission: ', req.params.permissionId, ' with: ', req.body, '\n');
const query = { 'meta.permissions._id': req.params.permissionId }
const update = { $set: { 'meta.permissions.$.permission': req.body } };
const options = { new: true};
table.update(query, update, options)
.then(savedTable => res.json(savedTable))
.catch((e) => { next(e); });
}
The console log displays the current table permissions and the req.params and req.body
Why the update statement doesn't run correctly
thanks for feedback
I found a way to solve this issue but I don't know if it's the best one ?
I update the table object using some() then I save the table..
function updatePermission(req, res, next) {
const table = req.table;
table.meta.permissions.some((obj, idx) => {
if (obj._id == req.params.permissionId) {
table.meta.permissions[idx].permission = req.body;
return true;
}
return false;
});
table.save()
.then(savedTable => res.json(savedTable))
.catch(e => next(e); );
}

Resources