I am working on node.js express framework and mongoose and I am totally new to it.
This is my schema.
const mongoose = require('mongoose');
const ActivitySchema = mongoose.Schema({
_id: mongoose.Schema.ObjectId,
Activity:String,
Photos:[{
Photo:String,
}]
});
module.exports = mongoose.model('Activity', ActivitySchema);
This is my code.I am getting success on deleting but data is not deleted from database.
router.delete('/removeactivity/:_id/:_pid', function (req, res) {
Activities.findByIdAndUpdate(
{ _id: req.params._id },
{ $pull: { Photos: { _id:req.params._pid } } },
function(err,user) {
if(err) {
res.status(500).json(err);
}
res.status(200).json(user)
}
);
})
You are using mongoose.Schema.ObjectId, so your _id field is an ObjectId. In the delete logic you pick req.params._id, which is, I guess, a string and not ObjectId, so it won't work.
To create an ObjectId from a string, use mongoose.Types.ObjectId like this:
Activities.findByIdAndUpdate(
{ _id: mongoose.Types.ObjectId(req.params._id) },
...
)
To get the new version of the document, after the update is applied, put {new: true} in the query. By default it is false.
Activities.findByIdAndUpdate(
{ _id: req.params._id },
{ $pull: { Photos: { _id:req.params._pid } } },
{new : true},
function(err,user) {
if(err) {
res.status(500).json(err);
}
res.status(200).json(user)
}
);
})
Related
All,
I can seem to figure out why the record in the database will not update. I am not 100% sure where my error is but this isn't really providing me a great error message. Can someone please take a look at this for me?
I believe that I am calling the mongoose request properly. Thank you in advance!
$ npm mongoose -v
8.15.0
const mongoose = require("mongoose");
const CartSchema = new mongoose.Schema(
{
owner: {
type: String,
unique: true,
required: true,
},
discount: {
type: Number,
},
total: {
type: Number,
},
items: [
{
itemId: {
type: Number,
},
sku: {
type: Number,
},
quantity: {
type: Number,
},
price: {
type: Number,
},
},
],
},
{ timestamps: true }
);
const Cart = mongoose.model("Cart", CartSchema);
module.exports = Cart;
Record in Database
{"_id":{"$oid":"630689708997a6589635986c"},
"owner":"611afa8b9069c9126cff3357",
"total":{"$numberInt":"0"},
"items":[],
"createdAt":{"$date":{"$numberLong":"1661372784844"}},
"updatedAt":{"$date":{"$numberLong":"1661372784844"}},
"__v":{"$numberInt":"0"}}
exports.add = async (req, res, next) => {
const { id, product } = req.body;
const addItem = { itemId: product._id, sku: product.sku, quantity: 1, price: product.price };
console.log(addItem);
try {
const updateCart = Cart.findByIdAndUpdate(id, { $addToSet: { items: addItem } }, { new: true, returnDocument: "after" });
if (!updateCart) return next(new ErrorResponse("Unable to update the cart record", 404));
console.log(updateCart);
if (updateCart) {
return sendRes(updateCart, 200, res);
} else {
return sendRes(updateCart, 201, res);
}
} catch (error) {
console.log(error);
next(error);
}
};
This issue was caused by me using an ASYNC Function without the AWAIT on the DB Call.
Please try once with this:
Cart.findByIdAndUpdate(id, { $addToSet: { items: addItem } }, { new: true, returnDocument: "after" });
The first obvious mistake is that you're searching for a document with the wrong field:"id", Kindly change that to "_id: id"
Also you might need to convert the _id string you have to MongoDB Object ID, like this:
const ObjectId = require('mongodb').ObjectId;
Cart.updateOne({_id: new ObjectId(id)}, { $addToSet: { items: addItem } }, { new: true, returnDocument: "after" });
For other update method, you need to specify the field, and also convert it to a MongoDB ID
OR
Cart.findByIdAndUpdate(id, { $addToSet: { items: addItem } }, { new: true, returnDocument: "after" })
You do not to specify the field in findByIdAndUpdate, just pass the id to it.
I want to update my answer object inside answers array. I am using following schema
const mongoose = require("mongoose");
const { ObjectId } = mongoose.Schema;
const questionSchema = new mongoose.Schema(
{
postedBy: {
type: ObjectId,
required: true,
ref: "User",
},
question: {
type: String,
required: true,
},
photo: {
data: String,
required: false,
},
answers: [
{
userId: { type: ObjectId, ref: "User" },
answer: String,
},
],
questionType: {
data: String,
required: false,
},
},
{ timeStamps: true }
);
module.exports = mongoose.model("Question", questionSchema);
I am using updateOne method to update my answer in my db. Can anyone explain what is missing here. I am been trying to solve this since hours
exports.updateAnswer = (req, res) => {
const questionId = req.body.questionId;
const answerId = req.body.answerId;
Question.findOne({ _id: questionId }).exec((err, question) => {
if (err) {
res.status(400).json({
error: errorHandler(err),
});
return;
}
if (!question) {
res.status(400).json({
error: "question not found",
});
return;
}
});
Question.updateOne(
{ _id: answerId },
{
$set: {
"answers.$.answer": "This is update answer. My name is Ravi Dubey",
},
},
{ new: true },
(err, success) => {
if (err) {
res.status(400).json({
error: errorHandler(err),
});
}
res.json({
msg: "answer updated successfully",
success,
});
}
);
};
My result is coming successful but answer is not updating in db.
I am confused on Question.updateOne method.
Any help appreciated.
If you trying to query based on id of one of the documents in the answers array then instead of {_id: answerId} you need to provide {'answers._id': answerId}. And also if you need the updated document as result then you should use the findOneAndUpdate method.
Question.findOneAndUpdate(
{ "answers._id": answerId },
{ $set: { "answers.$.answer": "some answer" } },
{ new: true },
(err, data) => {
// handle response
}
);
I want to search and return all 'plays' based on if a relationship exists in the 'payees' array using mongoose and Node.js.
Here is the schema:
const playSchema = new Schema({
streamer: { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
song: { type: mongoose.Schema.Types.ObjectId, ref: 'Song' },
revenue: { type: Number },
createdAt: { type: Date },
payees: [ { type: mongoose.Schema.Types.ObjectId, ref: 'User' } ]
});
And here is what I am trying to do (just an example):
Play.aggregate([{ $match: { payees: { req.user.id } } }]);
You can use the $elemMatch operator.
The $elemMatch operator matches documents that contain an array field
with at least one element that matches all the specified query
criteria.
Playground
Sample route:
router.get("/plays", async (req, res) => {
const userId = req.user.id;
try {
let docs = await Play.find({
payees: {
$elemMatch: {
$eq: userId
}
}
});
res.send(docs);
} catch (err) {
console.log(err);
res.status(500).send("Something went wrong");
}
});
i'm trying to do a pretty simple operation, pull an item from an array with Mongoose on a Mongo database like so:
User.update({ _id: fromUserId }, { $pull: { linkedUsers: [idToDelete] } });
fromUserId & idToDelete are both Objects Ids.
The schema for Users goes like this:
var UserSchema = new Schema({
groups: [],
linkedUsers: [],
name: { type: String, required: true, index: { unique: true } }
});
linkedUsers is an array that only receives Ids of other users.
I've tried this as well:
User.findOne({ _id: fromUserId }, function(err, user) {
user.linkedUsers.pull(idToDelete);
user.save();
});
But with no luck.
The second option seem to almost work when i console the lenghts of the array at different positions but after calling save and checking, the length is still at 36:
User.findOne({ _id: fromUserId }, function(err, user) {
console.log(user.linkedUsers.length); // returns 36
user.linkedUsers.pull(idToDelete);
console.log(user.linkedUsers.length); // returns 35
user.save();
});
So it looks like i'm close but still, no luck. Both Ids are sent via the frontend side of the app.
I'm running those versions:
"mongodb": "^2.2.29",
"mongoose": "^5.0.7",
Thanks in advance.
You need to explicitly define the types in your schema definition i.e.
groups: [{ type: Schema.Types.ObjectId, ref: 'Group' }],
linkedUsers: [{ type: Schema.Types.ObjectId, ref: 'User' }]
and then use either
User.findOneAndUpdate(
{ _id: fromUserId },
{ $pullAll: { linkedUsers: [idToDelete] } },
{ new: true },
function(err, data) {}
);
or
User.findByIdAndUpdate(fromUserId,
{ $pullAll: { linkedUsers: [idToDelete] } },
{ new: true },
function(err, data) {}
);
I had a similar issue. I wanted to delete an object from an array, using the default _id from mongo, but my query was wrong:
const update = { $pull: { cities: cityId }};
It should be:
const update = { $pull: { cities: {_id: cityId} }};
I'm trying to update a mongoose schema. Basically I have two api's '/follow/:user_id' and '/unfollow/:user_id'. What I'm trying to achieve is whenever user A follows user B , user B followers field in mongoose will increment as one.
As for now I managed to get only following fields increment by one but not the followers fields.
schema.js
var UserSchema = new Schema({
name: String,
username: { type: String, required: true, index: { unique: true }},
password: { type: String, required: true, select: false },
followers: [{ type: Schema.Types.ObjectId, ref: 'User'}],
following: [{ type: Schema.Types.ObjectId, ref: 'User'}],
followersCount: Number,
followingCount: Number
});
Updated version: I tried my solution, but whenever I post it, it just fetching the data ( I tried the api's on POSTMAN chrome app ).
api.js
// follow a user
apiRouter.post('/follow/:user_id', function(req, res) {
// find a current user that has logged in
User.update(
{
_id: req.decoded.id,
following: { $ne: req.params.user_id }
},
{
$push: { following: req.params.user_id},
$inc: { followingCount: 1}
},
function(err) {
if (err) {
res.send(err);
return;
}
User.update(
{
_id: req.params.user_id,
followers: { $ne: req.decoded.id }
},
{
$push: { followers: req.decoded.id },
$inc: { followersCount: 1}
}
), function(err) {
if(err) return res.send(err);
res.json({ message: "Successfully Followed!" });
}
});
});
These codes only manage to increment the user's following fields, and without duplication. How do I update logged in user's following fields and as well as other user's followers fields at the same time?
Updated version: it keeps fetching the data.
May be this is how you want to. Instead of using update, you can also use findOneAndUpdate from Mongoose queries.
apiRouter.post('/follow/:user_id', function(req, res) {
User.findOneAndUpdate(
{
_id: req.decoded.id
},
{
$push: {following: req.params.user_id},
$inc: {followingCount: 1}
},
function (err, user) {
if (err)
res.send(err);
User.findOneAndUpdate(
{
_id: req.params.user_id
},
{
$push: {followers: req.decoded.id},
$inc: {followersCount: 1}
},
function (err, anotherUser) {
if (err)
res.send(err);
res.json({message: "Successfully Followed!"})
});
});
}
If you are not sure about it is updated or not, you can just use console.log() for both user and anotherUser variables to see changes.