Update specific index of array in MongoDB - arrays

I would like to update the shipping property in my MongoDb (CRUD).
Shipping is an array property that contains object[index]. How to update the specific object such as index1 or index2.
This show the shipping property that contains two objects
If I want to update Object only at index 1 on the providerName, how can I do that
exports.updateShpping = (req, res) => {
const {shipping} = req.body;
Shop.findOne({ _id: req.shop._id }, (err, shop) => {
if (!shipping) {
return res.status(400).json({
error: 'shipping is required'
});
} else {
shop.shipping.push(shipping) ;
}
shop.save((err, addShipping) => {
if (err) {
console.log('Shipping ADD ERROR', err);
return res.status(400).json({
error: 'Shipping add failed'
});
}
res.json(addShipping);
});
});exports.updateShpping = (req, res) => {
const {shipping} = req.body;
Shop.findOne({ _id: req.shop._id }, (err, shop) => {
if (!shipping) {
return res.status(400).json({
error: 'shipping is required'
});
} else {
shop.shipping.push(shipping) ;
}
shop.save((err, addShipping) => {
if (err) {
console.log('Shipping ADD ERROR', err);
return res.status(400).json({
error: 'Shipping add failed'
});
}
res.json(addShipping);
});
});
};

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

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

JSX if/else syntax within React

I'm trying to figure out how to add an if/else here so that if classroomId has a value, the importUserToClassroom endpoint will be hit. If not, I'd like to execute the same code, but with the importUsers endpoint. Any ideas on where I'm going wrong with my syntax would be much appreciated!
handleFormSubmit(data) {
const {
importUserToClassroom,
importUsers,
addFlashMessage,
formatErrors,
showUiBlocked,
hideUiBlocked,
match: {params: {classroomId}},
} = this.props;
showUiBlocked();
const users = userDataToList(data);
{
classroomId !== undefined ? (
importUserToClassroom({
users,
classroomId,
})
) : (
importUsers({users})
)
}
.then(() => {
hideUiBlocked();
addFlashMessage('Users imported successfully', 'success');
this.context.router.history.push('/users');
})
.catch(err => {
hideUiBlocked();
if (err.status !== 409) {
return formatErrors(err).then(err => {
this.setState({
errors: err,
});
});
} else {
this.setState({
errors: {
usernames: err.data.message,
}
});
}
});
}
Update: The following ended up working!
handleFormSubmit(data) {
const {
importUserToClassroom,
importUsers,
addFlashMessage,
formatErrors,
showUiBlocked,
hideUiBlocked,
match: {params: {classroomId}},
} = this.props;
showUiBlocked();
const users = userDataToList(data);
if (!isEmpty(classroomId)) {
importUserToClassroom({
users,
classroomId,
})
.then(() => {
hideUiBlocked();
addFlashMessage('Users imported successfully', 'success');
this.context.router.history.push('/users');
})
.catch(err => {
hideUiBlocked();
if (err.status !== 409) {
return formatErrors(err).then(err => {
this.setState({
errors: err,
});
});
} else {
this.setState({
errors: {
usernames: err.data.message,
}
});
}
});
} else {
importUsers({users})
.then(() => {
hideUiBlocked();
addFlashMessage('Users imported successfully', 'success');
this.context.router.history.push('/users');
})
.catch(err => {
hideUiBlocked();
if (err.status !== 409) {
return formatErrors(err).then(err => {
this.setState({
errors: err,
});
});
} else {
this.setState({
errors: {
usernames: err.data.message,
}
});
}
});
}
}
This isn't really JSX, but you do have some syntax errors. You can't use curly brackets like that. If importUserToClassroom and importUsers return promises, you could try something like this:
const savePromise = classroomId ?
importUserToClassroom({
users,
classroomId,
}) :
importUsers({users});
savePromise.then(() => {
hideUiBlocked();
addFlashMessage('Users imported successfully', 'success');
this.context.router.history.push('/users');
})

Render template after fetching data from mongodb

app.get('/clients', (req, res) => {
var clientArray;
MongoClient.connect('mongodb://localhost:27017/Clients', (err, db) => {
if (err) {
return console.log('Unable to Connect');
}
console.log('Connected to Mongodb server');
db.collection('Clients').find().toArray().then((docs) => {
clientArray = JSON.stringify(docs, undefined, 2);
// clientArray = docs;
console.log(clientArray);
}, (err) => {
console.log("ERROR")
});
db.close();
});
res.render('clients.hbs', {
infoArray: clientArray,
name: 'Harshit'
});
});
Here the res.render function is being called before getting the required data from the mongodb database. I want to pass the data fetched as an array to the handlebars template.
{{#each infoArray}}
<h1>{{this.name}}</h1>
{{this.region}}
{{/each}}
Here I am trying to go through the array rendered and display the data.Any Help is appreciated.
Structure of array
[{
"name": "harshit",
"region": "delhi"
},
{
"name": "mendax",
"region": "ecuador"
}
]
Render has to be in callback function :
app.get('/clients', (req, res) => {
var clientArray;
MongoClient.connect('mongodb://localhost:27017/Clients', (err, db) => {
if (err) {
return console.log('Unable to Connect');
}
console.log('Connected to Mongodb server');
db.collection('Clients').find().toArray().then((docs) => {
clientArray = JSON.stringify(docs, undefined, 2);
// clientArray = docs;
console.log(clientArray);
db.close();
res.render('clients.hbs', {
infoArray: clientArray,
name: 'Harshit'
});
}, (err) => {
console.log("ERROR")
db.close();
});
});
});
You are almost there.
This is happening becuse MongoClient.connect(.. is asynchronous. So you res.render executes before that.
What you need is, just move your res.render inside that block
app.get('/clients', (req, res) => {
var clientArray;
MongoClient.connect('mongodb://localhost:27017/Clients', (err, db) => {
if (err) {
return console.log('Unable to Connect');
}
console.log('Connected to Mongodb server');
db.collection('Clients').find().toArray().then((docs) => {
clientArray = JSON.stringify(docs, undefined, 2);
// clientArray = docs;
res.render('clients.hbs', {
infoArray: clientArray,
name: 'Harshit'
});
}, (err) => {
console.log("ERROR")
});
db.close();
});
});

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