MongoDB pushing objects to array within object - arrays

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})
}
})

Related

Mongoose/Mongodb getting .deleteOne is not a function

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

How to get all the data from Mongo db collection in my MEAN stack app?

I am creating a MEAN stack app I have mongo DB (atlas) connected to it (working properly) but now I want to get all the data that I stored in my database. How can I do that?
Below is my code snippet-
this is my .ts file
constructor(private route: ActivatedRoute, private router: Router, private ds: DataService) { }
getAllLocations(){
this.ds.getLocations().subscribe((d) => {
this.locationObject = d;
console.log(this.locationObject);
})
}
this is my data service file
getLocations():any{
return this.http.get('http://localhost:3000/get-locations');
}
this is my index.js file(react file)
app.post('/get-locations', bodyParser.json(), (req, res) => {
var collection = connection.db(dbName).collection('user_2');
collection.find({}).toArray((err, docs) => {
if (!err) {
res.send({ status: "ok", data: docs })
}
else {
res.send({ status: "failed", data: err });
}
})
})
all this code is giving me 2 errors
GET http://localhost:3000/get-locations 404 (Not Found)
ERROR HttpErrorResponse {headers: HttpHeaders, status: 404, statusText: "Not Found", url: "http://localhost:3000/get-locations", ok: false, …}
Also, my database is not empty and has this type of structure like-
{ latitude : value, longitude : value}
{ latitude : value, longitude : value}
{ latitude : value, longitude : value}
change the request method to get
app.get('/get-locations', bodyParser.json(), (req, res) => {
var collection = connection.db(dbName).collection('user_2');
collection.find({}).toArray((err, docs) => {
if (!err) {
res.send({ status: "ok", data: docs })
}
else {
res.send({ status: "failed", data: err });
}
})
})
here is the solution
this.ds.getLocations()
.subscribe((response)=>{
if(response.status=="ok")
{
alert('locations fetched successfully');
// console.log(response.data);
this.userlist = response.data;
this.checkingNearby();
}
else{
alert("locations cant be fetched ");
// alert(JSON.stringify(response.data));
}
})
getLocations():any{
return this.http.post('http://localhost:3000/get-locations',"");
}
and its working.

Json; how can I return my res array of MongoDB Models to Router's .get, as json? (Node js)

I can successfully connect, query & find all of the files that I want from my database, according to my model.
But I can't actually return them as JSON yet... so my question is, how can I return this following result (console.log of res):
Into JSON for my get request?
My model with most vars snipped for brevity:
const fileSchema = new mongoose.Schema({
fileName: { type: String },
versionData: [
{
versionID: { type: Number, required: false
}
]
});
This is my main code where I am trying to return my res as JSON so that my Get request can be properly processed and display the results. I've tried returning JSON.stringify(res), but that didn't seem to work.
// Controller code
findAll = function() {
File.find({}, function(err, res) {
if (err) console.log(err);
else {
// Res is populated successfully
console.log(res);
return res.json(); // JSON.stringify(res)
}
});
};
Router:
// Return all results
router.get("/findAll", ctrlFile.findAll);
Thank you
Hey so I got this working by changing:
findAll = function() {
File.find({}, function(err, res) {
if (err) console.log(err);
else {
return res.json();
}
});
};
To:
findAll = (req, res) => {
File.find({}, function(err, result) {
if (err) console.log(err);
else {
return res.json({ result });
}
});
};

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

Express API DELETE

I am trying to add DELETE to my api, but am getting a 404: Not Found for everything I try. All of the GET and POST methods work. This is using the "Points" model that contains points, each with a unique id. I am trying to add a call to delete a point by its id.
Action
export function deletePointById(identifier) {
return dispatch => {
return axios.delete('/api/points/' + identifier)
}
}
Route for DELETE (doesn't work)
router.delete('/:identifier', (req, res) => {
Points.remove({
id: req.params.identifier
}), function (err, user) {
if (err) {
return res.send(err);
}
res.json({ message: 'Deleted' });
};
});
Here is an existing GET that works fine
Action
export function getPointsBySession(session){
return dispatch => {
return axios.get('/api/points/session/' + session)
}
}
Route for GET
router.get('/session/:session', (req, res) => {
Points.query({
select: ['id', 'number', 'quadrant', 'level', 'title', 'category'],
where: {sessionId: req.params.session}
}).fetchAll().then(point => {
res.json({ point });
})
});
It looks like your issue might be that theres an extra brace and semicolon ( };) in your code:
router.delete('/:identifier', (req, res) => {
Points.remove({
id: req.params.identifier
}), function (err, user) {
if (err) {
return res.send(err);
}
res.json({ message: 'Deleted' });
}; // <-- HERE
});
You also need to remove the semicolon on the line above the one I added the comment to.
It will look like this:
router.delete('/:identifier', (req, res) => {
Points.remove({
id: req.params.identifier
}), function (err, user) {
if (err) {
return res.send(err);
}
res.json({ message: 'Deleted' })
});

Resources