Mongoose/Mongodb getting .deleteOne is not a function - reactjs

When I click to delete a post, my console is saying TypeError: post.user.posts.deleteOne is not a function. It giving me this error after deleting.
const post = await Post.findByIdAndDelete(id).populate('user'); This code I am deleting the post from Post Schema
await post.user.posts.deleteOne(post)This code is to delete the post from the User Schema. I populated user and assigned it to post and then delete the user's post from this code, but I'm getting the error here.
Below is the controller code
export const deletePost = async (req, res) => {
const { id } = req.params;
try {
const post = await Post.findByIdAndDelete(id).populate('user');
await post.user.posts.deleteOne(post)
if (!post) {
return res.status(500).json({ message: "Unable To Delete" })
}
res.status(200).json({ message: "Deleted Successfully" })
} catch (error) {
console.log(error);
}
}
Client side delete request
const handleDeleteTrue = async () => {
try {
const { data } = await api.delete(`/post/${id}`)
console.log(data)
window.location.reload();
} catch (error) {
console.log(error.response.data.message);
}
};
User model schema
import mongoose from 'mongoose';
const userSchema = new mongoose.Schema({
name: {
type: String,
required: true
},
username: {
type: String,
required: true,
unique: true
},
email: {
type: String,
required: true,
unqie: true
},
password: {
type: String,
required: true,
minlength: 6
},
posts: [{ type: mongoose.Types.ObjectId, ref: "Post", required: true }]
});
export default mongoose.model('User', userSchema);
Im able to delete the post from the post model schema, but in this pic, which shows the user model schema, that same post that was deleted is not deleted here. This is the problem Im trying to solve.

What I can seem to understand in your function below is that you're trying to delete a single post and also checking if post exists first
export const deletePost = async (req, res) => {
const { id } = req.params;
try {
const post = await Post.findByIdAndDelete(id).populate('user');
await post.user.posts.deleteOne(post)
if (!post) {
return res.status(500).json({ message: "Unable To Delete" })
}
res.status(200).json({ message: "Deleted Successfully" })
catch (error) {
console.log(error);
}
}
I'd suggest you try this
export const deletePost = async (req, res) => {
const { id } = req.params;
try {
//check if document exists in mongoDB collection
if (!mongoose.Types.ObjectId.isValid(id)) {
return res.status(500).json({ message: "Unable To Delete" }) }
await Post.deleteOne(id)
res.status(200).json({ message: "Deleted Successfully" })
catch (error) {
console.log(error);
}
}

I found out the answer. My user model schema for post was an array so I had to use $pull to delete it.
This is the code that worked for me
await post.user.posts.pull(post)
await post.user.save()

You can't use findOneAndDelete on populate to delete one object from an array. it doesn't work that way. Use This Instead.
const result = await User.findOneAndUpdate(
{ _id: Id },
{ $pull: { post:PostId } },
{ new: true }
);
You can find More on Pull and Push Operations on BlogLink

Related

How to make the mongoose update array work properly?

this is my schema.it has a user field and an array of object which contains a text message and direction will hold a either sent or received value.
const MessageSchema = new mongoose.Schema({
user:{type: String,required: true},
textArray:[
{
text:{type: String,required: true},
direction:{ type: String,required: true }
}]
});
This is the router code.btw should there be double quotes on the keys in var textmessage?
router.post('/',async(req,res)=>{
const {user,text,direction}=req.body;
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
var textmessage={
"text":text,
"direction":direction
}
const doc = await Message.updateOne(
{ user: user },
{ $set: { user:user,$push:{textArray:textmessage}} },
{ upsert: true },
function(err,result){
if (err){
console.log(err);
}
else{
console.log(result)
res.send(result)
}// Make this update into an upsert
});
})
this is how it showsup in mongodb.the user is working ok but when i click theres is nothing under textArray.What am I doing wrong exactly?
you are using await with callback function , which is wrong :
const filter = { user: user };
const update = { $push:{textArray:textmessage}};
let doc = await Message.findOneAndUpdate(filter, update, {
new: true,
upsert: true
});
console.log('doc=',doc);

Mongoose NextJS OverwriteModelError: Cannot overwrite `Note` model once compiled

I am learning to use Mongoose with NextJS and I keep running into this error. I have looked over similar questions but didn't figure out how to solve this. I have followed a tutorial video for implementing Mongoose step by step but in the video this problem didn't occur. Also, I hate to say it this inaccurately but it only happens "sometimes". Seems like every time I run the server first POST request always goes through, GET requests are also fine but when I try multiple POST requests it occurs. After restarting the server it works again. Here is my code:
import mongoose from "mongoose"
const connection = {}
async function dbConnect() {
if (connection.isConnected) {
retrun
}
const db = await mongoose.connect(process.env.MONGO_URI, {
useNewUrlParser: true,
useUnifiedTopology: true,
})
connection.isConnected = db.connections[0].readyState
console.log(connection.isConnected)
}
export default dbConnect
const mongoose = require("mongoose")
let NoteSchema = new mongoose.Schema({
email: {
type: String,
required: [true, "Please enter your email"]
}
})
module.exports = mongoose.model.Note || mongoose.model("Note", NoteSchema);
import dbConnect from "../../utils/dbConnect"
import Note from "../../models/Note"
dbConnect()
export default async (req, res) => {
const { method } = req
switch(method) {
case "GET":
try {
const notes = await Note.find({})
res.status(200).json({ success: true, data: notes })
} catch (error) {
res.status(400).json({ success: false })
}
break
case "POST":
try {
const note = await Note.create(req.body)
res.status(201).json({ success: true, data: note })
} catch (error) {
res.status(400).json({ success:false })
}
break
default:
res.status(400).json({ success:false })
break
}
}
Thanks for any help.
you should use mongoose.models.Note instead of mongoose.model.Note
so just try:
module.exports = mongoose.models.Note || mongoose.model("Note", NoteSchema);
This method is used to prevent overwrite model once compiled Mongoose

MongoDB pushing objects to array within object

I am trying to push a new object to an array with objects inside another object (see DB Schema here: MongoDB set-up). Trying to push to notes within subtopics[2] object within the topic.
This is the code but it ends up deleting the specified subtopic id:
router.patch('/:topicId/:subtopicId/note', async (req, res) => {
try {
const subtopicNote = await Note.update(
{_id: req.params.topicId},
{subtopics :
{ _id: req.params.subtopicId,
$push: {
notes:
{note: req.body.note}
}
}
}
);
res.json(subtopicNote);
} catch (err) {
res.json({ messsage: err})
}
})
This worked for me :)
router.patch('/:topicId/:subtopicId/note', async (req, res) => {
try {
const subtopicNote = await Note.updateOne(
{_id: req.params.topicId, subtopics : {"$elemMatch": {"_id":req.params.subtopicId}}},
{ $push : {
'subtopics.$.notes': {note: req.body.note}
}
}
)
res.json(subtopicNote);
} catch (err) {
res.json({ message: err})
}
})

Pushing data from React in array in MongoDB

I want to push a string in an array in a MongoDB document using React/NodeJS/MongoDB,
Here's my code in React
async function toggleLike() {
try {
const dataUser = await axios.post(
`http://localhost:5000/user/${props.auth.user.id}/add/moviesLiked/${props.match.params.id}`);
console.log("user ", dataUser);
forceUpdate();
} catch (error) {
console.log(error);
}
Here's my code in NodeJS
router.post("/user/:user/add/moviesLiked/:movie", function(req, res) {
console.log("in api function add");
mongo.connect(
url,
{
useNewUrlParser: true,
useUnifiedTopology: true
},
(err, client) => {
if (err) {
console.error(err);
return;
}
const db = client.db("ofilms-demo");
const collection = db.collection("users");
collection.update(
{ _id: req.params.user },
{ $addToSet: { moviesLiked: req.params.movie } }
);
console.log("req params user ", req.params.user);
console.log("req params movie ", req.params.movie);
client.close();
}
);
});
Here's the model of an user in Mongoose
const UserSchema = new Schema({
moviesLiked: Array,
moviesDisliked: Array,
});
All my console.log show the right thing, but I still don't have the data pushed in the array,
Can somebody help me ? Thank you,
collection.update is asynchronous, so you need to wait for it to finish executing before closing your connection to Mongo and returning a response to the client.
You can wait for the update operation to complete by either passing a call back to the update method or using the async/await javascript feature.
Passing a call back function:
router.post("/user/:user/add/moviesLiked/:movie", function (req, res) {
mongo.connect(
url,
{
useNewUrlParser: true,
useUnifiedTopology: true
},
(err, client) => {
if (err) {
console.error(err);
return;
}
const db = client.db("ofilms-demo");
const collection = db.collection("users");
collection.update(
{ _id: req.params.user },
{ $addToSet: { moviesLiked: req.params.movie } },
function (error, result) { // The callback function
if (error) {
// Handle the error and send a respone to the user
} else {
// Make use of the result and send a response to the user
}
client.close();
}
);
}
);
});
Using async/await:
// Add the async keyword before declaring the function
router.post("/user/:user/add/moviesLiked/:movie", async function (req, res) {
mongo.connect(
url,
{
useNewUrlParser: true,
useUnifiedTopology: true
},
(err, client) => {
if (err) {
console.error(err);
return;
}
const db = client.db("ofilms-demo");
const collection = db.collection("users");
try {
// Add the await keyword before the update call
await collection.update(
{ _id: req.params.user },
{ $addToSet: { moviesLiked: req.params.movie } },
);
// Send response to your client
} catch (err) {
// Handle any possible error
}
client.close();
console.log("req params user ", req.params.user);
console.log("req params movie ", req.params.movie);
}
);
});
After DB i/o operation is done you should send back the response to your client something like this:
use try-catch to get the error message without crashing the whole node server.
Don't forget to send back the response to client otherwise, the client-side will keep waiting for server response until it's timeout reached
Node.js
router.post("/user/:user/add/moviesLiked/:movie", async (req, res) =>{
console.log("in api function add");
mongo.connect(
url,
{
useNewUrlParser: true,
useUnifiedTopology: true
},
(err, client) => {
if (err) {
console.error(err);
res.status(500).send({"message":"error occured", err})
return;
}
try{
const db = client.db("ofilms-demo");
const collection = db.collection("users");
const response = await collection.update(
{ _id: req.params.user },
{ $addToSet: { moviesLiked: req.params.movie } }
);
console.log("req params user ", req.params.user);
console.log("req params movie ", req.params.movie);
//send back the response
res.status(200).send({response, "message":"your profile is successfully updated."})
client.close();
}catch(err){
//check what is the error in your Nodejs console (Not browser console)
console.log(err)
//send back response
res.status(500).send({"message":"error occured", err})
}
);
}
});
MongoDB is itself schema-less. you don't have to provide schema. if you want to provide your own schema I'd recommend using mongoose. & mongoose arrays

mongoose findOne method is returning null

I am following this tutorial. Even though code is exactly what is mentioned in the tutorial, every time i run the graphql mutation query to update a particular tweet, it returns null and logs null on cmd.
I verified mongoose version is same (4.11.3).I believe something is wrong with findOne method as even in deleteTweet resolver, findOne is returning null. Is it because findOne needs a callback? but in the tutorial there is no callback passed. I also noticed that findOneAndUpdate works fine but it creates a new entry rather updating the existing tweet.
updateTweet: async (_, { id, ...rest}, { user }) => {
try {
await requireAuth(user)
const tweet = await Tweet.findOne({ id, user: user.id });
console.log(tweet);
if(!tweet) {
throw new Error('Not Found!');
}
return tweet.save();
} catch (e) {
throw e;
}
},
deleteTweet: async (_, { id }, { user }) => {
try {
await requireAuth(user);
const tweet = await Tweet.findOne({ id, user: user.id });
if(!tweet) {
throw new Error('Not Found !')
}
await tweet.remove();
return {
message: "Deleted Tweet Successfully"
}
}catch(error) {
throw error;
}
}
}
TweetSchema
import mongoose, { Schema } from 'mongoose';
const TweetSchema = new Schema({
text: {
type: String,
minlength: [5, 'Text need to be longer'],
maxlength: [144, 'Text is too long'],
},
user: {
type: Schema.Types.ObjectId,
ref: 'User'
},
favoriteCount: {
type: Number,
default: 0
}
}, { timestamps: true})
export default mongoose.model('Tweet', TweetSchema);
You have a typo. In MongoDB, the key field is _id NOT id. This is added automatically by MongoDB unless provided, so you need to change your code to use _id instead.

Resources