so I'm trying to update a document but it just doesn't work with _id but if I filter with "name" it works
I also tried with FindByID and it returns null
using mongoose version 5.0.18
const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/mongo-exercises')
.then(() => console.log('connected to database :)'))
.catch(reason => console.log('Can not connect to data base',reason));
const courseSchema = mongoose.Schema({
name: String,
author: String,
tags: [String],
Date: { type:Date,default:Date.now },
isPublished: Boolean,
price: Number
});
const Course = mongoose.model('courses',courseSchema);
async function updateCourse(id){
let result = await Course.update({_id: id},{
$set:{
author: "some random dude",
isPublished: true
}
});
console.log('result: ',result);
}
updateCourse('5a68fde3f09ad7646ddec17e');
try using
//make sure you import Course module
Course.findByIdAndUpdate(id)
.then(response=>{
})
.catch(err=>{
})
I just had to re-import the collection without _id so it can regenerate them
Related
Mongoose newbe here. I got the following function to update the references (deleting them) in the document Post when a Tag is deleted. When I call my GraphQl API this is what I got:
message": "posts.save is not a function"
The function in my gql resolver:
async deleteTag(root, { id }, context) {
const posts = await Post.find();
const tag = await Tag.findById(id);
if(!tag){
const error = new Error('Tag not found!');
error.code = 404;
throw error;
}
posts?.forEach(async (post) => {
await post.tags.pull(id);
})
await posts.save()
await Tag.findByIdAndRemove(id);
return true;
}
This is the Post model:
const PostSchema = new Schema({
body: {
type: String,
required: true
},
tags: {
type: [Schema.Types.ObjectId],
ref: 'Tag',
required: false
},
});
and this is the Tag model:
const TagSchema = new Schema(
{
name: {
type: String,
required: true
},
},
{ timestamps: true }
);
Looks like I can't call the method save() on the array of objects returned by Exercise.find()
I used the same pattern in other functions, the difference is that there I used .findById()
Any solution? Advice and best practice advide are super welcome.
You have to save the posts individually:
posts?.forEach(async (post) => {
await post.tags.pull(id);
await post.save();
})
Or use Model.updateMany() combined with the $pull operator.
FWIW, you should probably limit the number of matching Post documents by selecting only documents that have the specific tag listed:
await Post.find({ 'tags._id' : id });
Even though the question have been asked numerous time none of the answers have any idea to help me .
This is my mongoose Schema
const mongoose = require('mongoose')
const { Schema } = mongoose;
const recipeSchema = new Schema({
name: { type: String, required: true },
description: { type: String, required: true },
imagePath: { type: String, required: true },
ingredients:[
{
name:{type:String, required:true},
amount:{type:Number,required:true }
}
]
})
module.exports = mongoose.model("Recipe",recipeSchema);
what i need is to get the data from angular and store it to my database using node
const Recipe = require('../models/recipe.model');
const recipeCtrl={};
recipeCtrl.CreateRecipeServer =async(req, res, next)=>{
if(!req.file) {
return res.status(500).send({ message: 'Upload fail'});
}
else {
let ingredientArray=new Array()
ingredientArray.push(req.body.ingredients)
req.body.imageUrl = 'http://192.168.0.7:3000/images/' + req.file.filename;
const recipe=new Recipe({
name:req.body.name,
description:req.body.description,
imagePath:req.body.imageUrl,
ingredients:[
{
name:ingredientArray,
amount:ingredientArray }
]
});
await recipe.save();
}
Everything except the ingredients array works perfectly/as i require.
I am getting the ingredients as an array from formdata so it have to be JSON.stringfied inorder to append with the form. So what i am getting at backend is string . eg
**[{"name":"dasdasd","amount":2},{"name":"fsfsd","amount":2},{"name":"sdfsdgd","amount":3}]**
this is a string. Any ideas on how to convert it and store to database
use JSON.parse and choose first element of that
JSON.parse(data)[0]
Users are able to post items which other users can request. So, a user creates one item and many users can request it. So, I thought the best way would be to put an array of users into the product schema for who has requested it. And for now I just want to store that users ID and first name. Here is the schema:
const Schema = mongoose.Schema;
const productSchema = new Schema({
title: {
type: String,
required: true
},
category: {
type: String,
required: true
},
description: {
type: String,
required: true
},
userId: {
type: Schema.Types.ObjectId,
ref: 'User',
required: true
},
requests: [
{
userId: {type: Object},
firstName: {type: String}
}
],
});
module.exports = mongoose.model('Product', productSchema);
In my controller I am first finding the item and then calling save().
exports.postRequest = (req, res, next) => {
const productId = req.body.productId;
const userId = req.body.userId;
const firstName = req.body.firstName;
const data = {userId: userId, firstName: firstName};
Product.findById(productId).then(product => {
product.requests.push(data);
return product
.save()
.then(() => {
res.status(200).json({ message: "success" });
})
.catch(err => {
res.status(500).json({message: 'Something went wrong'});
});
});
};
Firstly, is it okay to do it like this? I found a few posts about this but they don't find and call save, they use findByIdAndUpdate() and $push. Is it 'wrong' to do it how I have done it? This is the second way I tried it and I get the same result in the database:
exports.postRequest = (req, res, next) => {
const productId = req.body.productId;
const userId = req.body.userId;
const firstName = req.body.firstName;
const data = {userId: userId, firstName: firstName};
Product.findByIdAndUpdate(productId, {
$push: {requests: data}
})
.then(() => {
console.log('succes');
})
.catch(err => {
console.log(err);
})
};
And secondly, if you look at the screen shot is the data in the correct format and structure? I don't know why there is _id in there as well instead of just the user ID and first name.
Normally, Developers will save only the reference of other collection(users) in the collection(product). In addition, you had saved username also. Thats fine.
Both of your methods work. But, second method has been added in MongoDB exactly for your specific need. So, no harm in using second method.
There is nothing wrong doing it the way you have done it. using save after querying gives you the chance to validate some things in the data as well for one.
and you can add additional fields as well (if included in the Schema). for an example if your current json return doesn't have a field called last_name then you can add that and save the doc as well so that's a benefit..
When using findById() you don't actually have the power to make a change other than what you program it to do
One thing I noticed.. In your Schema, after you compile it using mongoose.modal()
export the compiled model so that you can use it everywhere it's required using import. like this..
const Product = module.exports = mongoose.model('Product', productSchema);
I am trying out nodejs and using mongoose to save a document to mangoDB but my validation for name which I set to required : true is not working. Though I have not set name field the document gets saved. Am i missing an thing in my code
const courseSchema = new mongoose.Schema({
name: {type:String, requried:true},
author: String,
tags: [ String ],
date: Date,
isPublished: Boolean,
price: Number
});
const Course = mongoose.model('Course',courseSchema);
async function createCourse() {
try {
const course = new Course({
author: "Srikanth xyz",
tags: ['express','js'],
isPublished: true,
price: 15
});
const result = await course.save();
console.log(result);
} catch (error) {
console.log("ERROR: " + error.message);
}
}
createCourse();
You might want to double check "requried" to "required"
Here, the spelling of required is wrong. Correct it from
requried to required.
I am trying to update a collection using async/await. Below is my code:
const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost:27017/mongo-exercises')
.then(() => {
console.log('Connected to MongoDB');
UpdateCourse("5a68fdd7bee8ea64649c2777");
})
.catch(error => console.error('Could not connect to MongoDB : ' + error));
const courseSchema = mongoose.Schema({
name: String,
author: String,
tags: [String],
date: Date,
isPublished: Boolean,
price: Number
});
const Course = mongoose.model('course', courseSchema);
async function UpdateCourse(id) {
console.log(`Inside Update Course. Finding ${id}`);
const course = await Course.findById(id);
console.log(`Course: ${course}`);
if(!course)
return;
course.isPublished = true;
course.author = 'Another Author';
//course.set({isPublished: true, author: 'Another Author'});
const saved = await course.save();
console.log(saved);
}
I query the collection in mongo shell which produces the below output:
In the UpdateCourse() method I am getting null as value for course. I do have the id in the collection. Could anybody tell me why I am getting this error while using async/await.
I tried changing findById() -> findOne({_id: id}). Same error. I tried changing findById() -> find({_id: id}) here I am getting UnhandledPromiseRejectionWarning: Unhandled promise rejection.. Not understanding why.
The _id value in the document you're trying to find is a String, not an ObjectId. So you need to update your schema to define _id as a String; otherwise Mongoose will cast any _id values in your queries to the default _id type of ObjectId (resulting in the query not matching the document).
const courseSchema = mongoose.Schema({
_id: String,
name: String,
author: String,
tags: [String],
date: Date,
isPublished: Boolean,
price: Number
});
Having said all that, you probably want to update your documents to use ObjectId values for _id instead of String, as it's more efficient.