No matching document found for id error - javascript

I am facing two issues with the below code
Upon saving the document after put API call,it's throwing a message ' No matching document found for id \"59c6607a1608fe26e8c7f574\"" '
If required attribute value for each field is set as true then mongoose is throwing a validation error message stating that path not found.For eg if ii set addressLine1: { type: String, required: true } then it throws a validation message contact.addressLine1: Path contact.addressLine1 is required.However if required attribute is set to false then no validation error is thrown.
Can some one help me to correct the below code -
Model -
var localTransportSchema = new Schema({
providerID: {
type: Number,
required: true,
trim: true,
unique: false
},
name: {
type: String,
required: true,
trim: false
},
contact: {
addressLine1: {
type: String,
required: false
},
addressLine2: {
type: String,
required: false
},
city: {
type: String,
required: false
},
postalCode: {
type: Number,
required: false
},
primaryContactNumber: {
type: Number,
required: false
},
secondaryContactNumber: {
type: Number,
required: false
},
serviceActiveFlag: {
type: String,
required: false,
enum: ['Y', 'N']
},
},
vehicle: [{
vehicleType: {
type: String,
required: false,
enum: ['sedan', 'hatchback', 'suv', 'mpv', 'luxury']
},
activeFlag: {
type: String,
required: false,
enum: ['Y', 'N']
},
}]
});
Controller -
module.exports.updateLocalTransportVendorDtls = function(req, res) {
var transportSchema = new transportModel();
new Promise(function(resolve, reject) {
checkForNewVehicleType(req, function(doc) {
resolve(doc)
})
})
.then(function(doc) {
var updateJustServiceDtls = doc.split(/\|/)[2];
return addJustNewVehicleDetailsOnly(req, res)
}).then(function() {
transportSchema.save(function(error) {
if (error) {
logger.error("Error while updating record in transport details collection: - " + error.message)
return res.status(500).json({
"Message": error.message.trim()
});
}
})
}).catch(function(err) {
return res.json({
"Message": err.message
});
});
}
Function -
var addJustNewVehicleDetailsOnly = function(req, res) {
var promise = new Promise(function(resolve, reject) {
var updates = {
$set: {
"contact": {
"addressLine2": req.body['addressLine2'],
"secondaryContactNumber": req.body['secondaryContactNumber'],
"serviceActiveFlag": req.body['serviceActiveFlag']
},
"$push": {
"vehicle": {
"vehicleType": req.body['vehicleType'],
"chargePerKiloMeter": req.body['chargePerKM'],
"selfDriven": req.body['isSelfDriven'],
"additionalCharges": req.body['additionalCharges'],
"driverBata": req.body['driverBata'],
"activeFlag": req.body['vehicleActiveFlag']
}
}
}
}
transportModel.findOneAndUpdate({
"name": req.body['providerName'],
"contact.postalCode": parseInt(req.body['postalCode'])
},
updates, {
returnOriginal: false,
upsert: false
},
function(err, doc) {
if (err) {
logger.error("Error while updating record : - " + err.message);
return reject(res.status(409).json({
"Message": "Error while updating transport details for provider " + req.body['providerName'] + " in transport details table"
}));
} else if (doc === null) {
logger.error("Error while updating record in transport details : - unable to update database");
return reject(res.status(409).json({
"Message": "Error while updating transport details for provider " + req.body['providerName'] + " due to " + err.message
}));
}
return resolve();
});
})
return promise;
}

Related

mongoose find method return an empty array

here is my code and I can add tour on my database but cannot retrieve them and return empty arrray
any method that return certain document from my database it return empty array but if used same model to add document its added
the model is
const mongoose = require("mongoose");
const tourschema = new mongoose.Schema(
{
name: {
type: String,
required: true,
unique: [true, "the Name must br unique"],
trim: true,
maxLength: [40, "name of tour must be less than 40 character"],
minLength: [10, "name of tour must be more than 10"],
},
rating: { type: Number, default: 10 },
price: {
type: Number,
required: false,
},
duration: {
type: Number,
required: true,
},
maxGroupSize: {
type: Number,
required: true,
},
difficulty: {
type: String,
required: true,
enum: {
values: ["easy", "medium", "difficult"],
message: "Difficulty must be easy or medium or difficult",
},
},
ratingavg: {
type: Number,
default: 4.5,
min: [1, "Rating must be above 1,0"],
max: [5, "Rating must be below 5,0"],
},
ratingquantity: {
type: Number,
default: 0,
},
pricediscount: {
type: Number,
validate: {
validator: function () {
//this only point to current document
return this.pricediscount < this.price;
},
message: "Discount price must be less than price",
},
},
summary: {
type: String,
trim: true,
},
description: {
type: String,
trim: true,
required: true,
},
imageCover: {
type: String,
required: true,
},
images: [String],
createdAt: {
type: Date,
default: Date.now(),
},
startdates: [Date],
screttour: {
type: Boolean,
default: false,
},
},
//second object passed is schema option
{
//each time data is outputed as json
toJSON: { virtuals: true },
toObject: { virtuals: true },
}
);
//virtual means they ar not persist on database
tourschema.virtual("duration_in_weeks").get(function () {
return this.duration / 7;
});
tourschema.pre(/^find/, function (next) {
//this refer to query so we can chain
this.find({ screttour: { $ne: false } });
this.start = Date.now();
next();
});
tourschema.post(/^find/, function (doc, next) {
//this refer to query so we can chain
console.log(`Query took ${Date.now() - this.start} milliseconds!`);
next();
});
//aggregation middlewar
tourschema.pre("aggregate", function (next) {
//this refer to aggreagte pipeline
this.pipeline().unshift({ $match: { secrettour: { $ne: true } } });
next();
});
const tour = mongoose.model("newtour", tourschema);
module.exports = tour;
//another file calling the function
const tour = require("../models/tourmodel");
exports.get_tour_by_id = async (req, res) => {
try {
const founded_tour = await tour.find({});
res.status(200).json({
status: "success retrieve",
dataretrieved: founded_tour,
});
} catch (err) {
res.status(404).json({
status: "failed to retrieve",
});
}
};
I tried to rename my collection name because of mongoose is adding s to collection name from it self I expect to return document , this was work earlier but now it is not working can any one help?

why Virtual Populate not working on Node js and mongoose? Scenario : Product and Review by user

I have review and product model.If user give review on specific product(id) then it is stored in review model database but i donot like to store user review in product model database .so, i used virtual populate in product model instead of child referencing.After using virtual properties,if we use product id to see details,we can see review of user in json format but not saved in database.But the problem is my virtual properties (In Product Model) not working as it doesnt show review of user in json format when i send the request in that product id which already have review by user(stored in review model database).what is the problem here?
User Review on Product (id) stored in database
Sending Request of that product id to see review of user in json format using virtual properties(but no review found in json)
In Product Model
const productSchema = new Schema({
name: {
type: String,
required: true,
trim: true,
},
slug: {
type: String,
required: true,
unique: true,
},
price: {
type: String,
required: true,
},
quantity: {
type: Number,
required: true,
},
description: {
type: String,
required: true,
trim: true,
},
offer: {
type: Number,
},
discount: {
type: Number,
},
productPictures: [{
img: {
type: String,
},
}, ],
mainCategory: {
type: mongoose.Schema.Types.ObjectId,
ref: "category",
required: [true, "It is a required field"],
},
sub1Category: {
type: mongoose.Schema.Types.ObjectId,
ref: "category",
required: [true, "It is a required field"],
},
sub2Category: {
type: mongoose.Schema.Types.ObjectId,
ref: "category",
required: [true, "It is a required field"],
},
createdBy: {
type: mongoose.Schema.Types.ObjectId,
ref: "admin",
required: true,
},
vendor: {
type: mongoose.Schema.Types.ObjectId,
ref: "vendor",
},
createdAt: {
type: String,
default: moment().format("DD/MM/YYYY") + ";" + moment().format("hh:mm:ss"),
},
updatedAt: {
type: String,
default: moment().format("DD/MM/YYYY") + ";" + moment().format("hh:mm:ss"),
},
},
{
toJson: { virtuals: true },
toObject: { virtuals: true },
}
);
productSchema.virtual("reviews", {
ref: "review",
foreignField: "product",
localField: "_id",
// justOne: true
});
const Product = mongoose.model("product", productSchema);
module.exports = Product;
In Review Model
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const moment = require("moment");
const reviewSchema = new Schema({
user: {
type: mongoose.Schema.Types.ObjectId,
ref: "user",
required: [true, "Review must belong to user"],
},
product: {
type: mongoose.Schema.Types.ObjectId,
ref: "product",
required: [true, "Review must belong to the product"],
},
review: {
type: String,
required: [true, "Review cannot be empty"],
},
rating: {
type: Number,
min: 1,
max: 5,
},
createdAt: {
type: String,
default: moment().format("DD/MM/YYYY") + ";" + moment().format("hh:mm:ss"),
},
updateddAt: {
type: String,
default: moment().format("DD/MM/YYYY") + ";" + moment().format("hh:mm:ss"),
},
}, {
toJson: { virtuals: true },
toObject: { virtuals: true },
});
// pre middleware and populating user and product(we can also do populate in getAllReview in controller)
reviewSchema.pre(/^find/, function(next) {
// ^find here is we use regex and can able to find,findOne ...etc
this.populate({
path: "product",
select: " _id name",
}).populate({
path: "user",
select: " _id fullName",
});
next()
});
const Review = mongoose.model("review", reviewSchema);
module.exports = Review;
In Review.js
const Review = require("../../models/Review.Models")
exports.createReview = async(req, res) => {
const review = await Review.create(req.body)
return res.status(201).json({
status: true,
review
})
}
exports.getAllReviews = async(req, res) => {
try {
const reviews = await Review.find()
return res.status(200).json({
status: true,
totalReviews: reviews.length,
reviews
})
} catch (error) {
return res.status(400).json({
status: false,
error
})
}}
In Product.js
const Product = require("../../models/Product.Models");
exports.getProductDetailsById = async(req, res) => {
try {
const { productId } = req.params;
// const { productId } = req.body;
if (productId) {
const products = await Product.findOne({ _id: productId })
.populate('reviews')
return res.status(200).json({
status: true,
products,
});
} else {
console.log("error display");
return res.status(400).json({
status: false,
error: "params required...",
});
}
} catch (error) {
return res.status(400).json({
status: false,
error: error,
});
}
try this in Product.js
try {
if (productId) {
const products = await Product.findOne({ _id: productId }).populate(
"reviews"
);
console.log(products);
if (products) {
return res.status(200).json({
status: true,
message: "Products is listed",
products,
reviw: products.reviews,
});
only need to add on response sending
return res.status(200).json({
status: true,
message: "Products is listed",
products,
reviw: products.reviews,
});

How would I populate the mongoDB post schema with all comments for post?

I have build two schemas, one for posts and one for comments.
const PostSchema = new Schema(
{
title: { type: String, required: true },
text: { type: String, required: true },
author: { type: Schema.Types.ObjectId, ref: 'User', required: true },
status: { type: Boolean, default: true },
},
{ timestamps: true }
);
, and:
const CommentSchema = new Schema(
{
text: { type: String, required: true, minlength: 5 },
author: { type: String, required: true },
post: { type: Schema.Types.ObjectId, ref: 'Post' },
},
{
timestamps: true,
}
);
Now I want to make a GET request which finds all posts and would populate each post with its comments. So far I have this, but I am hitting a wall. If I try to do it like this, I can't add .toArray(), and it doesn't even add new field to the allPosts.
exports.allPosts_GET = (req, res) => {
Post.find()
.populate('author')
.sort('-createdAt')
.exec((err, allPosts) => {
if (err) {
return res.status(500).json({ success: false, msg: err.message });
} else if (allPosts.length === 0) {
return res.status(404).json({
success: false,
msg: 'No posts find in the database!',
});
}
allPosts.map((post) => {
post.comments = Comment.find({post: post._id}).
//to array somehow and populate all posts
});
console.log(allPostsStore);
res.status(200).json({ success: true, posts: allPosts });
});
};
So I came up with a solution, I updated my Post schema that contains an array with reference to ids of comments. Like that:
const PostSchema = new Schema(
{
title: { type: String, required: true },
text: { type: String, required: true },
author: { type: Schema.Types.ObjectId, ref: 'User', required: true },
comments: [{ type: Schema.Types.ObjectId, ref: 'Comment' }],
status: { type: Boolean, default: true },
},
{ timestamps: true }
);
And then when you make a new comment, you reference it to a post, and also save it to array of comments, like that:
exports.createNewComment_POST = (req, res) => {
const { text, author, postID } = req.body;
const newComment = new Comment({
text,
author,
post: postID,
});
newComment
.save()
.then((comment) => {
Post.findByIdAndUpdate(
postID,
{ $push: { comments: comment._id } },
{ new: true, useFindAndModify: false },
(err, post) => {
if (err) {
return res.status(500).json({ success: false, msg: err.message });
}
res.status(200).json({ success: true, comment });
}
);
})
.catch((err) => {
res.status(500).json({ success: false, msg: err.message });
});
};
Getting all posts with their comments, you just use find() and populate(), like that:
exports.allPosts_GET = (req, res) => {
Post.find()
.populate('author', '-password')
.populate('comments')
.sort('-createdAt')
.exec((err, posts) => {
if (err) {
return res.status(500).json({ success: false, msg: err.message });
} else if (posts.length === 0) {
return res.status(404).json({
success: false,
msg: 'No posts find in the database!',
});
}
res.status(200).json({ success: true, posts: posts });
});
};

Find One and Update in Mongoose with reference to other models is not working

I have a model named OrderModel and it has reference to other models as well
const orderSchema = new Schema({
_id: Schema.Types.ObjectId,
address: { type: addressSchema, required: false },
items: [{ type: Schema.Types.ObjectId, ref: 'Items' }],
date: { type: Date, default: moment(new Date()) },
user: { type: Schema.Types.ObjectId, ref: 'Users' },
is_completed: { type: Boolean, required: true, default: false },
is_canceled: { type: Boolean, required: true, default: false }
});
and when I want to update this model, using PATCH, it is giving me an error,
CastError: Cast to [ObjectId] failed for value "["5f0c9493f833e23a0028bd31,5f0c9429f833e23a0028bd2f"]" at path "items"
Here is how I do it in my code,
router.patch('/order', (req, res) => {
const query = { _id: req.body._id };
const _token = req.headers.authorization;
let data = req.body;
jwt.verify(_token, process.env.AUTH_TOKEN_KEY, (err, decoded) => {
console.log(query);
if (err) {
res.json({ message: 'Token Invalid'.err });
} else {
OrderModel.findOneAndUpdate(query, data, { new: true }, (err, doc) => {
console.log(doc,query);
if (doc) {
return res.json({ message: 'Succesfully saved', data: doc });
}
return res.json({ message: `No order found for id ${req.body._id}` });
});
}
})
})
i have two items as an Array, sent from frontend
{
"_id": "5f8f1b7b29cbed4a8495d646",
"items":"5f0c9493f833e23a0028bd31,5f0c9429f833e23a0028bd2f",
"user":"5f06060110b7881ac0244005",
"address":{
"line_1": "Address line 1",
"line_2": "Address line 1",
"city": "Los Angeles",
"state": "California",
"pin": "90210"
},
"is_completed": false,
"is_canceled": false
}
what am i doing wrong here?

Mongoose - when use populate no records otherwise array of records

I'm learning MeanJS and I have problem with Mongoose. I have two models:
var CategorySchema = new Schema({
name: {
type: String,
default: '',
required: 'Please fill Category name',
trim: true
},
slug: {
type: String,
default: '',
trim: true,
unique: true
},
created: {
type: Date,
default: Date.now
},
user: {
type: Schema.ObjectId,
ref: 'User'
},
articles: [{
type: Schema.ObjectId,
ref: 'Article'
}]
});
var ArticleSchema = new Schema({
created: {
type: Date,
default: Date.now
},
category: {
type: Schema.ObjectId,
ref: 'Category'
},
title: {
type: String,
default: '',
trim: true,
required: 'Title cannot be blank'
},
slug: {
type: String,
default: '',
trim: true,
unique: true
},
content: {
type: String,
default: '',
trim: true
},
user: {
type: Schema.ObjectId,
ref: 'User'
}
});
I'm saving articles like this:
exports.create = function(req, res) {
var article = new Article(req.body);
article.user = req.user;
article.save(function(err) {
if (err) {
return res.status(400).send({
message: errorHandler.getErrorMessage(err)
});
} else {
Category.findById(article.category).exec(function(err, category) {
category.articles.push(article.category);
category.save(function(err, category) {
if (err) {
return res.status(400).send({
message: errorHandler.getErrorMessage(err)
});
} else {
res.json(article);
}
});
});
}
});
};
and it's saving properly. The object looks like this:
{
"_id" : ObjectId("55b73bf97aa70c2c083655b0"),
"user" : ObjectId("55b115f35c7a03cc0e59d821"),
"articles" : [
ObjectId("55b73c017aa70c2c083655b2"),
ObjectId("55b73ee20bab5e8c0c7eadca")
],
"created" : ISODate("2015-07-28T08:23:21.562Z"),
"slug" : "motocycles",
"name" : "Motocycles",
"__v" : 2
}
and even when I'm counting records like {{ category.articles.length }} it's proper amount of articles in category and I can even print ObjectIds in the view. But when I add .populate('articles') like this:
exports.list = function(req, res) {
Category.find().sort('-created').populate('user', 'displayName').populate('articles').exec(function(err, categories) {
if (err) {
return res.status(400).send({
message: errorHandler.getErrorMessage(err)
});
} else {
res.jsonp(categories);
}
});
};
the length returns 0, ObjectIds disapears and I have no access to article properties just like there was no articles in category. Any ideas why is that happening?
Additional edit:
mongoose.model('Article', ArticleSchema);
mongoose.model('Category', CategorySchema);
It seems that the problem was with create function. I've changed few things and it started working:
exports.create = function(req, res) {
var article = new Article(req.body);
article.user = req.user;
article.save(function(err, savedArticle) {
if (err) {
return res.status(400).send({
message: errorHandler.getErrorMessage(err)
});
} else {
Category.findById(article.category).exec(function (err, category) {
category.articles.push(savedArticle);
category.markModified('articles');
category.save(function (err, category) {
if (err) {
return res.status(400).send({
message: errorHandler.getErrorMessage(err)
});
} else {
res.json(savedArticle);
}
});
});
}
});
};
I'm curious why it wasn't working even though Category object had proper Article ObjectId's.
First, some changes with regard to variables,schema instances and using ObjectId(The mongoose documentation isn't the best).
var categorySchema = new mongoose.Schema({
name: {
type: String,
required: 'Please fill Category name',
trim: true
},
slug: {
type: String,
trim: true,
unique: true
},
created: {
type: Date,
default: Date.now
},
user: {
type: mongoose.Types.Schema.ObjectId,
ref: 'User'
},
articles: [{
type: mongoose.Types.Schema.ObjectId,
ref: 'Article'
}]
});
var articleSchema = new mongoose.Schema({
created: {
type: Date,
default: Date.now
},
category: {
type: mongoose.Types.Schema.ObjectId,
ref: 'Category'
},
title: {
type: String,
trim: true,
required: 'Title cannot be blank'
},
slug: {
type: String,
trim: true,
unique: true
},
content: {
type: String,
trim: true
},
user: {
type: mongoose.Types.Schema.ObjectId,
ref: 'User'
}
});
You need to export your models if you are using an MV* pattern with separate files for separate concerns. So...
exports.method = mongoose.model('Category',categorySchema);
exports.otherMethod = mongoose.model('Article',articleSchema);
. method and .otherMethod are from nodejs. Not sure about express equivalent or what express itself uses.
Then just name this file and require it using its path.

Categories