Hello I'm making an Amazon clone, and I have this error
This is my code:
models/product.js
const mongoose = require("mongoose");
const ratingSchema = require("./rating");
const productSchema = mongoose.Schema({
name: {
type: String,
required: true,
trim: true,
},
description: {
type: String,
required: true,
trim: true,
},
images: [
{
type: String,
required: true,
},
],
quantity: {
type: Number,
required: true,
},
price: {
type: Number,
required: true,
},
category: {
type: String,
required: true,
},
ratings: [ratingSchema],
});
const Product = mongoose.model("Product", productSchema);
module.exports = { Product, productSchema };
routes/product.js
const ratingSchema = {
userId: req.user,
rating,
};
product.ratings.push(ratingSchema);
product = await product.save();
res.json(product);
} catch (e) {
res.status(500).json({ error: e.message });
}
});
productRouter.get("/api/deal-of-day", auth, async (req, res) => {
try {
let products = await Product.find({});
products = products.sort((a, b) => {
let aSum = 0;
let bSum = 0;
for (let i = 0; i < a.ratings.length; i++) {
aSum += a.ratings[i].rating;
}
for (let i = 0; i < b.ratings.length; i++) {
bSum += b.ratings[i].rating;
}
return aSum < bSum ? 1 : -1;
});
res.json(products[0]);
} catch (e) {
res.status(500).json({ error: e.message });
}
});
module.exports = productRouter;
I read a lot about this problem and to solve this error it is just adding an S on “exports” but I have it and got this error, so I don't know what I am missing.
For database language I'm using MongoDB, and I edit my user to admin profile and when I did that throw me this error, this is what I mean:
_id
63597582b96d28bbf4fba
name
"test"
email
"test#gmail.com"
password
"$0ZmF.eCD5zmB.etNxmGn22tTQqrCsrXkWMhO"
address
""
type
"admin "
__v
0
Related
I created an e-commerce website but want to change a couple of features of it, I want to allow users to create unlimited categories and subcategories. what is the best approach for it? I used Nodejs (express) and MongoDB (mongoose).
Currently, the DB schema is this one:
category.js
const mongoose = require('mongoose');
const { s, rs, n, ref } = require('../utils/mongo');
var schema = new mongoose.Schema(
{
user: ref('user'),
name: { ...rs, unique: true },
description: s,
image: s,
view: {
...n,
default: 0,
},
},
{ timestamps: true }
);
module.exports = mongoose.model('category', schema);
subcategory.js
const mongoose = require('mongoose');
const { s, rs, ref } = require('../utils/mongo');
var schema = new mongoose.Schema(
{
category: ref('category'),
name: { ...rs, unique: true },
description: s,
},
{ timestamps: true }
);
module.exports = mongoose.model('subcategory', schema);
Appreciate in advance
just use one model
import mongoose from "mongoose";
const CategorySchema = new mongoose.Schema({
name: {
type: String,
required: true,
unique: true
},
slug: {
type: String,
required: true,
unique: true
},
parent_id: {
type: mongoose.Schema.Types.ObjectId,
default: null
},
description: {
type: String,
default: null
},
image: {
url: String,
public_id: String
},
});
export mongoose.model('Category', CategorySchema);
// Create category
import { Category } from "./model/category.model"
const createCategory = async (data) => {
try {
return await new Category(data).save()
} catch (err) {
console.log(err)
}
}
// Get all category
const getAllCategory = async () => {
try {
const categories = await Category.find({});
if (!categories) return [];
return nestedCategories(categories);
} catch (err) {
console.log(err);
}
}
function nestedCategories(categories, parentId = null) {
const categoryList = [];
let category;
if (parentId == null) {
category = categories.filter(cat => cat.parent_id == null);
} else {
category = categories.filter(cat => String(cat.parent_id) == String(parentId));
}
for (let cate of category) {
categoryList.push({
_id: cate._id,
name: cate.name,
slug: cate.slug,
children: nestedCategories(categories, cate._id)
})
}
return categoryList;
}
If you want unlimited nested category you will only need one single category schema.
let schema = new mongoose.Schema(
{
user: ref('user'),
name: { ...rs, unique: true },
description: s,
image: s,
parent: { type: mongoose.Schema.Types.ObjectId }, //the parent category
view: {
...n,
default: 0,
},
},
{ timestamps: true }
);
module.exports = mongoose.model('category', schema);
Unfortunately, you cannot use populate and $lookup without specifying a specific level, so you need build the tree yourself if you need unlimited nested.
I've been going back and forth on this code for sometime now and I'm trying to have a totalQty value in the cart object that returns total number of items in the cart and I want to use that value in the views of course right next to the cart icon in the navigation. Here is my code for the user model and routes:
User model:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const userSchema = new Schema({
role: {
type: String,
default: 'BASIC'
},
firstName: {
type: String,
required: true
},
lastName: {
type: String,
required: true
},
address: {
type: String
},
apartment: {
type: String
},
country: {
type: String
},
state: {
type: String
},
city: {
type: String
},
zip: {
type: String
},
phone: {
type: String
},
email: {
type: String,
required: true
},
password: {
type: String,
required: true
},
resetToken: String,
resetTokenExpiration: Date,
cart: {
items: [
{
productId: {
type: Schema.Types.ObjectId,
ref: 'Product',
required: true
},
quantity: { type: Number, required: true }
},
],
totalQty: {
type: Number,
default: 0
}
}
}, { timestamps: true });
userSchema.methods.addToCart = function (product) {
const cartProductIndex = this.cart.items.findIndex(cp => {
return cp.productId.toString() === product._id.toString();
});
let newQuantity = 1;
// let newTotalQty = 1;
const updatedCartItems = [...this.cart.items];
if (cartProductIndex >= 0) {
newQuantity = this.cart.items[cartProductIndex].quantity + 1;
updatedCartItems[cartProductIndex].quantity = newQuantity;
newTotalQty = this.cart.totalQty + 1;
updatedTotalQty = newTotalQty;
} else {
updatedCartItems.push({
productId: product._id,
quantity: newQuantity
});
}
const updatedCart = {
items: updatedCartItems,
totalQty: updatedTotalQty
};
this.cart = updatedCart;
return this.save();
};
userSchema.methods.removeFromCart = function (productId) {
const updatedCartItems = this.cart.items.filter(item => {
return item.productId.toString() !== productId.toString();
});
this.cart.items = updatedCartItems;
return this.save();
};
userSchema.methods.clearCart = function () {
this.cart = { items: [] };
return this.save();
};
module.exports = mongoose.model('User', userSchema);
User routes:
exports.getCart = (req, res, next) => {
// populate req user
req.user
.populate('cart.items.productId')
.execPopulate()
.then(user => {
const products = user.cart.items;
// render cart view
res.render('shop/cart', {
path: '/cart',
pageTitle: 'Cart - Hashing365.com',
products: products
});
})
.catch(err => {
const error = new Error(err);
error.httpStatusCode = 500;
return next(error);
});
};
exports.postCart = (req, res, next) => {
// extract prod ID
const prodId = req.body.productId;
// run DB find with prod ID
Product.findById(prodId)
.then(product => {
// return true && add to cart
return req.user.addToCart(product);
})
.then(result => {
// re-render same page
res.redirect('back');
})
.catch(err => {
const error = new Error(err);
error.httpStatusCode = 500;
return next(error);
});
};
Would really appreciate if someone could help me with a way to do that. Thanks!
You can look into Array reducer function. It should look like this
cart.totalQty = cart.items.reduce((sum, item)=>{
return sum + item.quantity;
},0);
This is my Profile Schema:
const mongoose = require('mongoose');
const ProfileSchema = new mongoose.Schema({
user: {
// Special field type because
// it will be associated to different user
type: mongoose.Schema.Types.ObjectId,
ref: 'user',
},
company: {
type: String,
},
website: {
type: String,
},
location: {
type: String,
},
status: {
type: String,
required: true,
},
skills: {
type: [String],
required: true,
},
bio: {
type: String,
},
githubusername: {
type: String,
},
experience: [
{
title: {
type: String,
required: true,
},
company: {
type: String,
required: true,
},
location: {
type: String,
},
from: {
type: Date,
required: true,
},
to: {
type: Date,
},
current: {
type: Boolean,
default: false,
},
description: {
type: String,
},
},
],
education: [
{
school: {
type: String,
required: true,
},
degree: {
type: String,
required: true,
},
fieldofstudy: {
type: String,
required: true,
},
from: {
type: Date,
required: true,
},
to: {
type: Date,
},
current: {
type: Boolean,
default: false,
},
description: {
type: String,
},
},
],
social: {
youtube: {
type: String,
},
twitter: {
type: String,
},
facebook: {
type: String,
},
linkedin: {
type: String,
},
instagram: {
type: String,
},
},
date: {
type: Date,
default: Date.now,
},
});
module.exports = Profile = mongoose.model('profile', ProfileSchema);
This is my view api. It doesn't work. it only return Cast to ObjectId failed for value { 'experience._id': '5edcb6933c0bb75b3c90a263' } at path _id for model profile
router.get('/experience/viewing/:viewexp_id', auth, async (req, res) => {
try {
const exp = await Profile.findById({
'experience._id': req.params.viewexp_id,
});
if (!exp) {
return res.status(404).json({ msg: 'Experience not found' });
}
res.json(exp);
} catch (err) {
console.error(err.message);
res.status(500).send(err.message);
}
});
How can I fix this? I tried looking at the stackoverflow of the same errors. still it doesn't seem to work.
and this is what I am trying to hit
The problem is that you have to convert your string _id to mongoose object id using this function mongoose.Types.ObjectId and my suggestion is to use findOne function instead of findById,
var mongoose = require('mongoose');
router.get('/experience/viewing/:viewexp_id', auth, async (req, res) => {
try {
let id = mongoose.Types.ObjectId(req.params.viewexp_id);
const exp = await Profile.findOne(
{ "experience._id": req.params.viewexp_id },
// This will show your sub record only and exclude parent _id
{ "experience.$": 1, "_id": 0 }
);
if (!exp) {
return res.status(404).json({ msg: 'Experience not found' });
}
res.json(exp);
} catch (err) {
console.error(err.message);
res.status(500).send(err.message);
}
});
var mongoose = require('mongoose');
router.get('/experience/viewing/:viewexp_id', auth, async (req, res) => {
try {
const exp = await Profile.findOne({
'experience._id': mongoose.Types.ObjectId(req.params.viewexp_id),
});
if (!exp) {
return res.status(404).json({ msg: 'Experience not found' });
}
res.json(exp);
} catch (err) {
console.error(err.message);
res.status(500).send(err.message);
}
});
You are saving object id . but your param id is string. convert it in ObjectId. Please check my solution.
router.post(
"/",
[
auth,
[
check("status", "status is required").not().isEmpty(),
check("skills", "skills is required").not().isEmpty(),
],
],
async (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
const {
company,
website,
location,
bio,
status,
githubuername,
skills,
youtube,
facebook,
twitter,
instagram,
linkedin,
} = req.body;
const profileFileds = {};
profileFileds.user = req.user.id;
if (company) profileFileds.company = company;
if (website) profileFileds.website = website;
if (location) profileFileds.location = location;
if (bio) profileFileds.bio = bio;
if (status) profileFileds.status = status;
if (githubuername) profileFileds.githubuername = githubuername;
if (skills) {
profileFileds.skills = skills.split(",").map((skill) => skill.trim());
}
//Build profile object
profileFileds.social = {};
if (youtube) profileFileds.social.youtube = youtube;
if (twitter) profileFileds.social.twitter = twitter;
if (facebook) profileFileds.social.facebook = facebook;
if (linkedin) profileFileds.social.linkedin = linkedin;
if (instagram) profileFileds.social.instagram = instagram;
try {
let profile = await Profile.findOne({ user: req.user.id });
if (profile) {
//update
profile = await Profile.findOneAndUpdate(
{ user: req.user.id },
{ $set: profileFileds },
{ new: true }
);
return res.json(profile);
}
//Create profile
profile = new Profile(profileFileds);
await profile.save();
res.json(profile);
} catch (err) {
console.error(err.message);
res.status(500).send("server Error");
}
}
);
I am having an issue with mongoose and nodejs. May be i am writing wrong code or any other problem please help. Here is my controller file. alldata.save gives [ParallelSaveError]
let createData = async function(req,res,next) {
let body = req.body;
let alldata = new League(body);
let start_time = new Date().getTime();
try {
await Leaguecategories.find({})
.then(async function(categories) {
categories.forEach(async function(category) {
//here i am assigning foreign key
alldata.league_category_id = category._id;
await alldata.save(function(err, book){
if(err){
console.log(err);
}else{
res.send({status: 0, statusCode:"success", message: "Successfully inserted."})
}
});
})
})
}
catch (error){
return res.send({status : 1 , statusCode : "error" , message : error.message})
}
}
Here is my Leaguecategories model
var mongoose = require('mongoose');
const league_categories = new mongoose.Schema({
name: {
type: String,
required: true
},
active: {
type: String,
required: true
},
create_date: {
type: Date,
required: true,
default: Date.now
},
league_type_id: {
type: String,
required: 'league_type',
required:true
}
})
module.exports = mongoose.model('Leaguecategories', league_categories)
Here is my League model
var mongoose = require('mongoose');
const league = new mongoose.Schema({
title: {
type: String,
required: true
},
pool_price: {
type: Number,
required: true
},
entry_fee: {
type: Number,
required: true
},
total_spots: {
type: Number,
required: true
},
start_time: {
type: Date,
required: true
},
end_time: {
type: Date,
required: true
},
create_date: {
type: Date,
required: true,
default: Date.now
},
active: {
type: String,
required: true
},
league_category_id: {
type: String,
ref: 'Leaguecategories',
required:true
}
})
module.exports = mongoose.model('League', league)
You have to create new instance of League each time. Like this:
categories.forEach(async function(category) {
//here i am assigning foreign key
let alldata = new League(body);
alldata.league_category_id = category._id;
...
});
Suggestion:
Why are you using both async/await and .then()? You should use only one of them. Also, there are some other problems.
await won't work inside forEach
You are calling res.send() every time you call .save(). This might end up throwing an error as well.
You can refactor the code like this.
try {
const categories = await Leaguecategories.find({});
const promises = categories.map(function (category) {
//here i am assigning foreign key
let alldata = new League(body);
alldata.league_category_id = category._id;
return alldata.save();
});
await Promise.all(promises);
res.send({ status: 0, statusCode: "success", message: "Successfully inserted." })
} catch (error) {
return res.send({ status: 1, statusCode: "error", message: error.message });
}
I've got the following mongoose models:
Place.js
const mongoose = require("mongoose")
const Schema = mongoose.Schema
const placeSchema = new Schema({
title: { type: String, require: true },
filename: { type: String, require: true },
lociSets: [{ type: Schema.Types.ObjectId, ref: 'LociSet'}]
})
module.exports = mongoose.model("places", placeSchema)
LociSet.js
const mongoose = require("mongoose")
const Schema = mongoose.Schema
const LociSchema = require('./Locus')
const lociSetSchema = new Schema({
title: { type: String, require: true },
creator: { type: Schema.Types.ObjectId, ref: 'User' },
public: { type: Boolean, default: true },
loci: [LociSchema]
})
module.exports = mongoose.model("lociSets", lociSetSchema)
Locus.js
const mongoose = require("mongoose")
const Schema = mongoose.Schema
const locusSchema = new Schema({
position: {
x: { type: Number, require: true },
y: { type: Number, require: true },
z: { type: Number, require: true }
}
})
module.exports = locusSchema
Problem:
I try to insert a new LociSet into the lociSet array of Place like so:
exports.createOne = async (req, res) => {
const {
title,
public = true,
loci = []
} = req.body
console.log(title,public,loci,req.user.id)
const lociSet = new LociSet({
title,
public,
loci,
creator: req.user.id
})
try {
const place = await Place.findOne({
"title": req.params.title.toLowerCase()
})
console.log(lociSet)
await lociSet.save()
await place.lociSets.push(lociSet)
await place.save()
} catch (err) {
res.status(500).send({
message: "Some error occurred while creating the loci set.", err
});
}
}
But then I get an error message saying "Cast to [undefined] failed for value \"[{\"title\":\"Test set\",\"creator\":\"5a7898c403999200c4ee3ae5\",\"public\":\"true\"}]\" at path \"lociSets\""
The LociSet model is created without problems, but it seems to break when I try to save the place model
Because lociSets is an array of ObjectId references, you may want to try the following approach:
exports.createOne = async (req, res) => {
const { title, public = true, loci = [] } = req.body
const lociSet = new LociSet({
title,
public,
loci,
creator: req.user.id
})
try {
const newLociSet = await lociSet.save()
const place = await Place.findOneAndUpdate(
{ "title": req.params.title.toLowerCase() },
{ "$push": { "lociSets" : newLociSet._id } },
{ "new": true}
)
res.status(200).json(place)
} catch (err) {
res.status(500).send({
message: "Some error occurred while creating the loci set.", err
})
}
}