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?
Related
I have created the following schema in MongoDB. It is a customer schema with a sub-schema for storing the transactions. Each transaction is an object and each object(a transaction) contains a field called "transactionDetails", which is an object as well.
const transactionSchema = new Schema(
{
transactionType: {
type: String,
},
transactionDetails: {
transferredFrom: {
type: String,
default: "",
},
transferredTo: {
type: String,
default: "",
},
balance:{
type: Number,
default:0,
min: 0,
},
amount:{
type:Number,
default:0
}
},
},
{
timestamps: true,
}
);
const customerSchema = new Schema(
{
name: {
type: String,
required: [true, "Please provide a customer name"],
},
dob: {
type: Date,
required: [true, "Please provide a Date of Birth"],
},
address: {
type: String,
default: "India",
},
accNo: {
type: String,
required: true,
default: mongoose.Types.ObjectId,
},
email: {
type: String,
required: [true, "Please provide an email address"],
},
phone: {
type: String,
required: [true, "Please provide a phone number"],
},
transactions: [transactionSchema],
currentBal: {
type: Number,
required: [true, "Please provide valid balance"],
default: 0,
min:0
},
},
{
timestamps: true,
}
);
All I want to do is to set the value of a field to an existing field in the document while updating it. I want to set the value of "balance" field to the current updated value of the "currentBal" after the "currentBal" field has been updated.
The problem is that the no matter what I did, the value of "balance" field always set to default value without throwing any error
Customer.findOneAndUpdate(
{ accNo: id },
{
$inc: { currentBal: Number(amount),
},
$push: {
transactions: {
transactionType: "deposit",
transactionDetails: {
transferredFrom: "Self",
transferredTo: "Self",
balance:{currentBal} ,
amount: Number(amount),
},
},
},
},
(err, customer) => {
if (err !== null && err.name === "ValidationError") {
res.json({ message: err._message });
} else {
console.log("Balance has been updated successfully");
// console.log(customer.currentBal);
res.redirect(`/customers/${id}`);
}
}
);
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,
});
I have a database named "reviews" with a 9.7GB size. It has a collection name products. I was able to optimize the READ request using indexing technical by running the command db.products.ensureIndex({product_name: 1}); When I run the following command db.products.find({product_name:"nobis"}).explain("executionStats"); in MongoDB terminal, it shows that my execution time reduces from 28334ms to 3301ms.
I have the following 2 questions:
1) How do I use explain("executionStats"); on CREATE, PUT and DELETE requests? For example, I got this following error [thread1] TypeError: db.products.insert(...).explain is not a function when I tried to use the following insert function
db.products.insert({"product_id": 10000002,"product_name": "tissue","review": [{"review_id": 30000001,"user": {"user_id": 30000001,"firstname": "Peter","lastname": "Chen","gender": "Male","nickname": "Superman","email": "hongkongbboy#gmail.com","password": "123"},"opinion": "It's good","text": "It's bad","rating_overall": 3,"doesRecommended": true,"rating_size": "a size too big","rating_width": "Slightly wide","rating_comfort": "Uncomfortable","rating_quality": "What I expected","isHelpful": 23,"isNotHelpful": 17,"created_at": "2007-10-19T09:03:29.967Z","review_photo_path": [{"review_photo_id": 60000001,"review_photo_url": "https://sdcuserphotos.s3.us-west-1.amazonaws.com/741.jpg"}, {"review_photo_id": 60000002,"review_photo_url": "https://sdcuserphotos.s3.us-west-1.amazonaws.com/741.jpg"}]}, {"review_id": 30000002,"user": {"user_id": 30000002,"firstname": "Peter","lastname": "Chen","gender": "Male","nickname": "Superman","email": "hongkongbboy#gmail.com","password": "123"},"opinion": "It's good","text": "It's bad","rating_overall": 3,"doesRecommended": true,"rating_size": "a size too big","rating_width": "Slightly wide","rating_comfort": "Uncomfortable","rating_quality": "What I expected","isHelpful": 23,"isNotHelpful": 17,"created_at": "2007-10-19T09:03:29.967Z","review_photo_path": [{"review_photo_id": 60000003,"review_photo_url": "https://sdcuserphotos.s3.us-west-1.amazonaws.com/741.jpg"}]}]}).explain("executionStats");
2) Is there any performance Optimization method I can use for the CREATE, PUT and DELETE requests? For example, I am able to use POSTMAN to get the response time of a DELETE request, but the response time takes 38.73seconds.
const deleteReview = (request, response) => {
const id = parseInt(request.params.id);
Model.ProductModel.findOneAndDelete({ "review.review_id": id}, (error, results) => {
if (error) {
response.status(500).send(error);
} else {
response.status(200).send(results);
}
});
};
This is my MongoDB schema:
const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/reviews', { useNewUrlParser: true, useUnifiedTopology: true, useCreateIndex: true });
const Schema = mongoose.Schema;
const productSchema = new Schema({
product_id: { type: Number, required: true, unique: true },
product_name: { type: String, required: true, unique: true },
review: [{
review_id: { type: Number, required: true, unique: true },
user: {
user_id: { type: Number },
firstname: { type: String },
lastname: { type: String },
gender: { type: String, enum: ['Male', 'Female', 'Other'] },
nickname: { type: String },
email: { type: String, required: true },
password: { type: String, required: true },
},
opinion: { type: String, required: true },
text: { type: String },
rating_overall: { type: Number, min: 1, max: 5, required: true },
doesRecommended: { type: Boolean, required: true },
rating_size: { type: String, enum: ['a size too small', '1/2 a size too small', 'Perfect', '1/2 a size too big', 'a size too big'], required: true },
rating_width: { type: String, enum: ['Too narrow', 'Slightly narrow', 'Perfect', 'Slightly wide', 'Too wide'], required: true },
rating_comfort: { type: String, enum: ['Uncomfortable', 'Slightly uncomfortable', 'Ok', 'Comfortable', 'Perfect'], required: true },
rating_quality: { type: String, enum: ['Poor', 'Below average', 'What I expected', 'Pretty great', 'Perfect'], required: true },
isHelpful: { type: Number, required: true, default: 0 },
isNotHelpful: { type: Number, required: true, default: 0 },
created_at: { type: Date, required: true },
review_photo_path: [{
review_photo_id: { type: Number },
review_photo_url: { type: String }
}]
}]
});
const ProductModel = mongoose.model('product', productSchema);
module.exports = { ProductModel };
If you do not have one, ensure you have an index of review.review_id on your products collection. You're using that to look up what to delete so it should be indexed.
I read your deleteReview function as deleting the product document that contains the review, not just removing the individual review -- is that what you expect?
You should be able to just $pull the review from the reviews array to get rid of it.
You can use explain on an update like so:
db.products.explain().update({...}, {...});
See: https://docs.mongodb.com/manual/reference/method/db.collection.explain/
You can explain:
aggregate()
count()
find()
remove()
update()
distinct()
findAndModify()
I am seeding my database for testing so I have inserted 15000 instructor data in database now for each instructor I want to insert 100 course. so I ran to for loop
first to get all instructor ids and second to store 100 course for that id of instructor but while inserting courses I get this type of error
E11000 duplicate key error collection: Courser.courses index: ratings.user_1 dup key: { : null }
Here is the code to enter course for each instructor
seedCourse: async (req, res, next) => {
try {
const instructors = await Instructor.find();
//const insrtuctor contains 15000 instructor
for(let oneInst of instructors) {
for(let i=0; i<=100; i++) {
const course = await new Course({
title: faker.lorem.sentence(),
description: faker.lorem.paragraph(),
author: oneInst._id,
prise: Math.floor(Math.random()*6 + 4),
isPublished: 'true',
tags: ["java", "Nodejs", "javascript"]
});
const result = await course.save();
await Instructor.findByIdAndUpdate(oneInst._id, { $push: { courses: result._id } });
console.log(`Instructor Id ${oneInst._id} Course added ${i}`);
}
}
} catch (error) {
next(error)
}
}
My course model definition looks something like this
const mongoose = require('mongoose');
const Course = mongoose.model('courses', new mongoose.Schema({
title: {
type: String,
required: true,
minlength: 3
},
author: {
type: mongoose.Schema.Types.ObjectId,
ref: 'instructor'
},
description: {
type: String,
required: true,
minlength: 5
},
ratings: [{
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'users',
required: true,
unique: true
},
rating: {
type: Number,
required: true,
min: 0,
max: 5
},
description: {
type: String,
required: true,
minlength: 5
}
}],
tags: [String],
rating: {
type: Number,
min: 0,
default: 0
},
ratedBy: {
type: Number,
min: 0,
default: 0
},
prise: {
type: Number,
required: function() { this.isPublished },
min: 0
},
isPublished: {
type: Boolean,
default: false
}
}));
module.exports = Course;
In your Course schema user in ratings array is an unique field. You are not giving any unique value while storing course in DB. First time it tool value as null but next time it is trying to save null value for user. Hence violating the schema.
Either remove unique:true or pass an unique value for user
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;
}