It says items is undefined - node.js

The code is show below.
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const user = new Schema({
name: {
type: String,
required: true
},
email: {
type: String,
required: true
},
password: {
type: String,
required: true
},
resetToken: String,
resetExpiration: String,
products: [{type: mongoose.Types.ObjectId, required: true, ref: 'Shop'}],
cart: {
items: [
{
productId: {type: mongoose.Types.ObjectId, ref: 'Shop', required: true},
quantity: {type: Number, required: true},
}
]
},
});
user.methods.addToCart = (product) => {
const itemIndex = this.cart.items.findIndex(prod => {
return prod.productId.toString() === product._id.toString();
});
let newQuantity = 1;
const updatedCartItems = [...this.cart.items];
if(itemIndex >= 0) {
newQuantity = this.cart.items[itemIndex].quantity + 1;
updatedCartItems[itemIndex].quantity = newQuantity;
} else {
updatedCartItems.push({
productId: product,
quantity: newQuantity
});
}
const updatedCart = {
items: updatedCartItems
}
this.cart = updatedCart;
return this.save();
}
const model = mongoose.model('User', user);
module.exports = model;
I am trying to store product in the cart instance method as per above schema, but when i send product from my controller to addToCart it says items is undefined on this.cart.items. I haven't used instance method much in mongoose so, i don't know this issue is it with schema or general problem.
let me know if you need any other information.

It was a silly mistake, actually i was using arrow function. so it wasn't bind to schema.

Related

TypeError: Cannot read properties of null (reading 'idTechnical')

I was trying from some object get others info from it. Like from object A, get the objectId from object B, and printing the object B instead the object A. But I got this error message:
TypeError: Cannot read properties of null (reading 'idTechnical')
I'm using nodejs
My function:
const getFinalReport = async (req, res) => {
try{
const finalReport = await Final.findById(req.params.id);
const technicalReport = await Technical.findById(finalReport.idTechnical);
const finantialReport = await Finantial.findById(finalReport.idFinantial);
const writeReport = await Write.findById(finalReport.idWrite);
res.status(200).json(finalReport, {technicalReport, finantialReport, writeReport});
}catch(err){
console.error(err);
res.status(500).send({"msg": "Internal Error!"})
}}
My model:
const finalreportSchema = new mongoose.Schema({
idWrite: { type: mongoose.Schema.Types.ObjectId, ref: "reports", default:''},
idTechnical: { type: mongoose.Schema.Types.ObjectId, ref: "technincal", default: ''},
idFinantial: { type: mongoose.Schema.Types.ObjectId, ref: "finantial", default:''},
isConclude: { type: Boolean, default: false }
},
{
timestamps:true
});
const Report = mongoose.model('final-report', finalreportSchema);
module.exports = Report;
My techincal model:
const mongoose = require("mongoose");
const TechincalSchema = mongoose.Schema({
idInstallationNumber: { type: mongoose.Schema.Types.ObjectId, ref: "installations" },
months: { type: String, required: true },
previousBalance: { type: String, required: true },
actualBalance: { type: String, required: true },
injected: { type: String, required: true },
totalInjected: { type: String, required: true },
},
{
timestamps:true
});
const Technical = mongoose.model('technincal', TechincalSchema);
module.exports = Technical;
Same happen on the Finantial and Write Reports. Had someone had some clue?
Sorry for my english but, this is the first time asking, and also it's been a while that I write something in english (isn't my first language)

How to query based on related element's field value?

In my database, every article has its own 6-digit identifying number (in addition to id). Every comment belongs to one of the articles. My question is, how to query comments knowing only the article number, but not the article's id?
controllers/fetch-comments.js:
const Article = require('../models/article')
const User = require('../models/user');
const Comment = require('../models/comment');
module.exports = async function (req, res) {
try {
let { article_number, articleId } = req.body
let filter;
console.log(article_number)
/* Here is my failed attempt: */
if (article_number) filter = { 'article.number': article_number };
if (articleId) filter = { 'article': articleId };
let projection = null
let options = null
let comments = await Comment.find(filter, projection, options).populate('author', 'username fullname').lean()
return res.status(200).send(comments)
} catch (error) {
console.log("error on getting comments: " + error.message);
return res.status(500).send('Server side error');
}
}
models/article.js:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const articleSchema = new Schema({
author: { type: Schema.Types.ObjectId, ref: 'User', required: true },
title: { type: String, required: true },
content: { type: String, required: true },
coverPhotoUrl: { type: String, required: false },
number: { type: Number, required: true }, // number is public id for address bar
createdAt: { type: Date, required: true },
category: { type: String, required: false },
fake: { type: Boolean, required: false },
});
module.exports = mongoose.model('Article', articleSchema);
models/comment.js:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const commentSchema = new Schema({
author: { type: Schema.Types.ObjectId, ref: 'User', required: true },
content: { type: String, required: true },
createdAt: { type: Date, required: true },
article: { type: Schema.Types.ObjectId, ref: 'Article', required: true }
});
module.exports = mongoose.model('Comment', commentSchema);
Please do not suggest doing 2 queries intead of one, I already know how to do that.
You can use the aggregation framework and use a $match and $lookup operator to get the comment of a particular article number.
Following would be the code for the same:
db.Article.aggregate( [
{ $match : { number : article_number} },
{
$lookup:
{
from: "Comment",
localField: "_id",
foreignField: "article",
as: "article_comments"
}
}
] )
This will return an array of the matching comments.

How to use mongoose to make changes in two different collections in one nodejs query

In this application, I am trying to update a field value, if it is successful then I want to save into a log collection, however, not all the data are saved in the log collection, I am not sure if I am doing it the right way, would appreciate if someone could help out.
here is the query :
// both models(Log & Inventory are imported)
router.get("/add_product/:id/:num/:quantity/:order", (req, res) => {
var id = req.params.id;
var quantity = req.params.quantity;
var order = req.params.order;
// console.log('id----', id);
var num_mod = req.params.num;
var modified_count = parseInt(num_mod) - parseInt(quantity);
console.log("num_mod----", num_mod);
Inventory.findByIdAndUpdate(id, { quantity: parseInt(num_mod) }, { new: true }, function(
err,
inventory
) {
if (err) {
console.log("err", err);
res.status(500).send(err);
} else {
console.log(inventory.name);
const newLog = new Log({
name: inventory.name,
description: inventory.description,
price: parseInt(inventory.price),
quantity: parseInt(inventory.quantity),
modified_quantity: parseInt(modified_count),
itemDest: order //this is not being saved
});
newLog.save(function(err, Log) {
if (err) {
console.log(err);
} else {
console.log("add log success");
res.send(inventory);
}
});
}
});
});
URL from front end :
// order is a string
here is the Log schema :
const mongoose = require("mongoose");
const LogSchema = new mongoose.Schema(
{
// _id: mongoose.Schema.Types.ObjectId,
name: { type: String, required: true },
description: { type: String, required: true },
price: { type: Number, required: true },
quantity: { type: Number, required: true },
modified_quantity: { type: Number, required: true },
supplier: String,
taxable: Boolean,
itemDest: String
},
{ timestamps: true }
);
// Create model from the schema
const Log = mongoose.model("Log", LogSchema);
// Export model
module.exports = Log;
and here is the inventory schema
const mongoose = require("mongoose");
//create Schema
const InventorySchema = new mongoose.Schema(
{
// _id: mongoose.Schema.Types.ObjectId,
name: { type: String, required: true },
description: { type: String, required: true },
price: { type: Number, required: true },
quantity: { type: Number, required: true },
supplier: String,
taxable: Boolean
},
{ timestamps: true }
);
// Create model from the schema
const Inventory = mongoose.model("Inventory", InventorySchema);
// Export model
module.exports = Inventory;
My issue is with this line "itemDest: order" in the query, I intend to save the value of "order" extracted from "req.params.order" into "itemDest" but it doesn't save.

Mongoose populate returning data without population

I know that this question was asked many many times but i still can't find a solution
So this is my db
Product :
Ingredient :
Schemas :
ingredient.js
const mongoose = require("mongoose");
var IngredientSchema = new mongoose.Schema({
quantity: {
value: Number,
unit: String
},
comment: String,
product: { type: mongoose.Schema.Types.ObjectId, ref: "Product" }
});
module.exports = mongoose.model("IngredientSchema", IngredientSchema);
product.js
const mongoose = require("mongoose");
var ProductSchema = new mongoose.Schema({
name: {
type: String,
default: "",
trim: true,
required: "Name cannot be blank"
},
category: {
type: String,
default: "",
trim: true
},
convertion: [
{
unit_from: String,
unit_to: String,
value_from: Number,
value_to: Number
}
],
default_unit: String
});
const Product = (module.exports = mongoose.model(
"ProductSchema",
ProductSchema
));
this is the populate function :
ingredientRoutes.route("/:id").get(function(req, res) {
let id = req.params.id;
Ingredient.findById(id)
.populate("produit")
.exec()
.then(function(data) {
console.log(data.product, "***");
})
.catch(function(err) {
console.log(err);
});
});
this is the result that i'm getting :
just the id of the product without making the population
Any idea ?

Cast to ObjectId failed for value "" at path "_id" for model

I have already checked the other entries on StackOverflow, but it did not help.
I am building a RESTapi with node.js, and I am using MongoDB with mongoose
I have a Schema that contains three different models. I am able to save POST request to the entry. I am sure that entry is saved because I checked on atlas.mongo. However, I have a problem when I am trying to use GET request.
It gives this error:
Cast to ObjectId failed for value "" at path "_id" for model
These are my Models: (These models are in different files)
const Model1 = mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
word1: { type: [String], require: true }
});
----------------------------------------------
const Model2 = mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
word2: { type: [String], require: true }
});
----------------------------------------------
const Model3 = mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
element1: { type: [String], default: ""},
element2: { type: [String], default: ""}
});
----------------------------------------------
const Word = mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
md3: { type: mongoose.Schema.Types.Mixed, ref: 'Model3', require: true },
md2: { type: mongoose.Schema.Types.Mixed, ref: 'Model2', require: true },
md1: { type: mongoose.Schema.Types.Mixed, ref: 'Model1', require: true }
});
This is my POST request:
exports.entry_create = (req, res, next) => {
const newModel3 = new Model3({
_id: new mongoose.Types.ObjectId(),
element1: req.body.element1,
element2: req.body.element2
});
const newModel2 = new Model2({
_id: new mongoose.Types.ObjectId(),
word2: req.body.word2
});
const newModel1 = new Model1({
_id: new mongoose.Types.ObjectId(),
word1: req.body.word1
});
const newEntry = new Word({
_id: new mongoose.Types.ObjectId(),
md3: newModel3,
md2: newModel2,
md1: newModel1
});
newEntry
.save(); // i have also then() and catch() part
};
This is where I got the error on Postman
exports.entry_get_all = (req, res, next) => {
Word.find()
.select('_id md3 md2 md1')
.populate('md3')
.populate('md2')
.populate('md1')
.exec()
.then(docs => {
res.status(200).json({
numOfEntries: docs.length,
Entries: docs.map(doc => {
return {
_id: doc._id,
md3: doc.md3,
md2: doc.md2,
md1: doc.md1,
request: { type: 'GET' }
}
})
});
}); // i have also catch() part
};
What could be the problem? Is _id's of md3, md2 & md1 returns null?
I believe it has to do with your references md1, md2 and md3. The way you reference another model is by the _id, which in your case it's and ObjectId. That being said, when you define md1, md2, and md3 you say the type is mixed, not an ObjectId. Do this instead:
const Word = mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
md3: { type: mongoose.Schema.Types.ObjectId, ref: 'Model3', require: true },
md2: { type: mongoose.Schema.Types.ObjectId, ref: 'Model2', require: true },
md1: { type: mongoose.Schema.Types.ObjectId, ref: 'Model1', require: true }
});
Also note: You don't need to explicitly create a new ObjectId when creating an instance of your model. If using mongoose, it creates the _id for you! So you can just create a new Word like this:
let md1 = null;
let md2 = null;
let md3 = null;
const newModel3 = new Model3({
element1: req.body.element1,
element2: req.body.element2
});
// Save newModel3
newModel3.save()
.then((_md3) => {
md3 = _md3;
const newModel2 = new Model2({
word2: req.body.word2
});
return newModel2.save();
})
.then((_md2) => {
md2 = _md2;
const newModel1 = new Model1({
word1: req.body.word1
});
return newModel1.save();
})
.then((_md1) => {
md1 = _md1
const newEntry = new Word({
md3: md3._id,
md2: md2._id,
md1: md1._id
});
return newEntry.save();
})

Resources