I want to find an existing id object when I post a bill, but I don't know how find it to save the bill. I want it works from back end and front end.
This is my bill model:
const mongoose = require("mongoose");
const { Schema } = mongoose;
const billSchema = new Schema({
number: Number,
date: { type: Date, default: Date.now() },
type: String,
local: String,
client: {
type: mongoose.Schema.Types.ObjectId,
ref: "clients"
},
provider: {
type: mongoose.Schema.Types.ObjectId,
ref: "providers"
},
detail: [
{
quantity: Number,
product: {
code: Number,
name: String,
price: Number
},
undertotal: Number
}
],
total: Number
});
module.exports = mongoose.model("bills", billSchema);
And this is my post service:
app.post("/api/bills", async (req, res) => {
const { number, type, local, detail, total } = req.body;
let existingClient = await Client.findById(Client._id);
if (!existingClient) {
return res.status(404).json({
message: "not found client"
});
}
let existingProvider = await Provider.findById(Provider._id);
if (!existingProvider) {
return res.status(404).json({
message: "not found provider"
});
}
if (
!existingClient._id ||
(existingClient._id &&
mongoose.Types.ObjectId() ===
(await Client.findById(existingClient._id).select("_id")))
) {
const clientId = mongoose.Types.ObjectId();
this.existingClient._id = clientId;
}
if (
!existingProvider._id ||
(existingProvider._id &&
mongoose.Types.ObjectId() ===
(await Provider.findById(existingProvider._id).select("_id")))
) {
const providerId = mongoose.Types.ObjectId();
this.existingProvider._id = providerId;
}
const bill = new Bill({
number,
date: new Date(),
type,
local,
client: clientId,
provider: providerId,
detail,
total
});
try {
let newBill = await bill.save();
res.status(201).send(newBill);
} catch (err) {
if (err.name === "MongoError") {
res.status(409).send(err.message);
}
console.log(err);
res.status(500).send(err);
}
});
The expected output is bill saved with client and provider ids but real output is an error message saying "cannot read property _id of undefined"
What is wrong?
Related
I am trying to add query params that allow the api user to have the option to sort by descending order based on the title field and to limit the the amount items the query returns. But when I call the endpoint it still just returns the data unsorted and without the limit applied to it.
getCourses = async (req, res) => {
try {
const limit = req.query.limit | 20;
if (req.query.desc === "true") {
const data = await courseModel.find().sort({ title: -1 }).limit(limit);
return res.json(data);
} else {
const data = await courseModel.find().aggregate({ $limit: limit });
return res.json(data);
}
} catch (error) {
return res.status(500).json({ message: error.message });
}
};
const courseSchema = mongoose.Schema({
title: {
type: String,
required: true
},
description: {
type: String,
required: true
},
category: {
type: String,
required: true
},
price: {
type: Number,
required: true
},
length: {
type: Number,
required: true
}
})
const CourseMessge = mongoose.model('CourseMessage', courseSchema);
module.exports = CourseMessge
This is how i am calling the end point:
localhost:3000/api/courses?desc=true&limit=10
You should use the || operator for specifying a default value for the limit.
Also, try to cast the desc parameter to a string:
getCourses = async (req, res) => {
try {
const limit = req.query.limit || 20;
if (req.query.desc.toString() === 'true') {
const data = await courseModel.find().sort({ title: -1 }).limit(limit);
return res.json(data);
} else {
const data = await courseModel.find().limit(limit);
return res.json(data);
}
} catch (error) {
return res.status(500).json({ message: error.message });
}
};
I am using Express.js, Node.js, MongoDB, and Mongoose stack
I have three documents in the database which are Warehouses, Inventories, and Items.
A Warehouse has one Inventory, and each Inventory is assigned to a Warehouse.
An Inventory contains many Items.
items.model.js
const mongoose = require('mongoose');
const itemSchema = new mongoose.Schema({
name:{
type: String
},
dateCreated:{
type: Date,
default: Date.now()
},
price:{
type:Number
},
type:{
type:String
},
category:{
type:String
},
description:{
type: String
},
picture:{
type: String
}
})
const Item = mongoose.model('item',itemSchema)
module.exports.Item=Item
module.exports.itemSchema = itemSchema
inventories.model.js
const mongoose = require('mongoose');
const itemSchema = require('../items/items.model').itemSchema;
const inventorySchema = new mongoose.Schema({
name:{
type: String,
unique: true
},
dateCreated:{
type: Date
},
items:{
type:[itemSchema]
}
})
const Inventory = mongoose.model('inventory',inventorySchema)
module.exports.inventorySchema=inventorySchema;
module.exports.Inventory=Inventory;
warehouses.model.js
const mongoose = require('mongoose');
const inventorySchema = require('../inventories/inventories.model').inventorySchema
const warehouseSchema = new mongoose.Schema({
name:{
type:String
},
location:{
type:String
},
inventory:{
type:inventorySchema
},
dateCreated:{
type:Date,
default:Date.now()
},
numberOfEmployees:{
type:Number
}
})
const Warehouse = mongoose.model('warehouse',warehouseSchema)
module.exports.Warehouse=Warehouse
I have an endpoint which assigns an Inventory to a Warehouse based on the Inventory's name. I also have an endpoint that adds an Item to an Inventory
warehouses.controller.js
/**
*
* Assign an inventory to warehouse based on
* Warehouse (id), inventory (name)
*/
const assignInventory = () => async (req, res) => {
try {
const inventoryName = req.body.inventory
const inventoryDoc = await Inventory.findOne({ name: inventoryName })
if (!inventoryDoc) {
return res.status(404).json('No Inventory with this ID exists!')
}
const warehouseID = req.params.id
const doc = await Warehouse.findByIdAndUpdate(
{ _id: warehouseID },
{ ...req.body, inventory: inventoryDoc }
)
if (!doc) {
return res.status(404).end()
}
return res.status(200).json({
message: 'Assigned Inventory to warehouse successfully',
data: doc
})
} catch (error) {
console.error(error)
res.status(400).end()
}
}
inventories.controller.js
/**
*
* Add an Item to an Inventory based on
* Inventory (id), Item (name)
*/
const addItemToInventory = () => async(req,res)=>{
try {
//Retreive the inventory id from the URL Parameters
const inventoryID= req.params.id
//Retreive the item name from the request body
const itemName= req.body.name;
//Fetch the item document from the database based on the request body
const itemDoc = await Item.find({name:itemName})
if(!itemDoc)
{
return res.status(404).json(`Can't find item with this name`)
}
console.log(itemDoc)
//Update the inventory with the the new item document added to its item list
const inventoryDoc = await Inventory.findById({_id:inventoryID})
console.log(inventoryDoc)
var inventoryList = inventoryDoc.items
console.log('Updated')
inventoryList.push(itemDoc)
console.log(inventoryList)
const updatedInventoryDoc = await Inventory.findByIdAndUpdate({_id:inventoryID},{$push:{items:itemDoc}})
if(!updatedInventoryDoc){
return res.status(404).end()
}
res.status(200).json({data: updatedInventoryDoc})
} catch (e) {
console.error(e)
}
}
The problem is that whenever I add an Item to an Inventory that is already assigned to a Warehouse, if I fetched that Warehouse, it will not show the added Item.
In the image above, I added an Item to the Inventory and fetched that Inventory.
The Inventory was previously added to a Warehouse.
Yet as seen above here, The Warehouse still has only one item inside it.
Is there anything that can reference an Inventory inside a Warehouse? so that after any update to any Inventory, the Warehouse will listen to these updates.
Thanks in advance.
Edit 1: Added Inventory, Warehouse, and Item models.
After searching I found out that I should change the structure of the warehouse.model.js to make it referring to the ObjectID of an Inventory, so it is going to look like this.
const mongoose = require('mongoose');
const inventorySchema = require('../inventories/inventories.model').inventorySchema
const warehouseSchema = new mongoose.Schema({
name:{
type:String
},
location:{
type:String
},
//Instead of inventory:inventorySchema
inventory:{
type: mongoose.Schema.Types.ObjectId,
ref: "inventory"
},
dateCreated:{
type:Date,
default:Date.now()
},
numberOfEmployees:{
type:Number
}
})
const Warehouse = mongoose.model('warehouse',warehouseSchema)
module.exports.Warehouse=Warehouse
and inside the warehouses.controller.js, we should call populate on any database call that retrieves the Warehouse documents like this
const readWarehouse = () => async (req, res) => {
try {
const doc = await Warehouse.find({}).populate('inventory')
if (!doc) {
return res.status(404).end()
}
res.status(200).json({ data: doc })
} catch (e) {
console.error(e)
res.status(400).end()
}
}
const readOneWarehouse = () => async (req, res) => {
try {
const id = req.params.id
const doc = await Warehouse.findOne({ _id: id }).populate('inventory')
if (!doc) {
return res.status(404).end()
}
res.status(200).json({ data: doc })
} catch (e) {
console.error(e)
res.status(400).end()
}
}
Also updated the assignInventory() to be like that
const assignInventory = () => async (req, res) => {
try {
const inventoryName = req.body.inventory
const inventoryDoc = await Inventory.findOne({ name: inventoryName })
if (!inventoryDoc) {
return res.status(404).json('No Inventory with this ID exists!')
}
const inventoryDocID=inventoryDoc._id
const warehouseID = req.params.id
const doc = await Warehouse.findByIdAndUpdate(
{ _id: warehouseID },
{ ...req.body, inventory: inventoryDocID }
)
if (!doc) {
return res.status(404).end()
}
return res.status(200).json({
message: 'Assigned Inventory to warehouse successfully',
data: doc
})
} catch (error) {
console.error(error)
res.status(400).end()
}
}
this get route is giving no error in post-man but doing the same with frontend giving error in node console:
ObjectParameterError: Parameter "filter" to find() must be an object, got search
although response are fetched.
get controller
const Recent = require("../models/recent");
const getRecentByName = async (req, res, next) => {
const name = req.params.name;
let regex = new RegExp(name, "i");
let players;
try {
players = await Recent.find({ name: { $regex: regex } });
} catch (err) {
return next(err);
}
if (!players) {
return next("no player found");
}
// console.log(players);
res.json({ players });
};
exports.getRecentByName = getRecentByName;
fetching from frontend:
const searchRecords = async () => {
const data = await sendRequest(
"http://localhost:5000/api/player/recent/search/" + search,
"GET"
);
setRecord(data.players);
};
Recent:(mongoose Schema):
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const recentSchema = new Schema({
name: { type: String, required: true },
recent: [
{
team1: { type: String },
team2: { type: String },
points: { type: Number, required: true },
date: { type: Date },
},
],
});
module.exports = mongoose.model("Recent", recentSchema);
I think the problem is from the front and in the URL
you should use
http://localhost:5000/api/player/recent/search/${search}
I have Schema With name score, and that have an iduser: req.session.user._id.
and I have more than one items with same iduser. I wanna to find all the items with the same iduser. and I use the
var users = await storescors16.find({ id }) id = res.session.user._id.
but that show me all the items in score !
My code
//schema
const storescor = new mongoose.Schema({
iduser: String,
level: { type: String, default: null },
day: { type: String, default: null },
date: { type: String, default: null },
time: { type: String, default: null },
objectif: { type: String, default: null }
})
var storescors16 = mongoose.model("storescor", storescor);
//post infos to database
router.post('/control/edite-control', (req, res) => {
console.log(req.session.selectuserid);
var { level, day, date, time, ob } = req.body
var scor = new storescors16({
iduser: req.session.selectuserid,
level: level,
day: day,
date: date,
time: time,
objectif: ob,
})
//read infos from databse
router.get('/result', auth, async(req, res) => {
var id = req.session.user._id
console.log(id);
var user = User.findById(id, (err, docs) => {
if (err)
console.log(err);
else
console.log();
})
var ids = req.session.user._id
var notes = await storescors16.find({ ids })
console.log(notes);
let scor = user.quiz
res.render('./options/result', {
notes: notes,
scor: scor,
title: 'سجل درجات النجم',
name: session.user.name,
email: session.user.email,
})
});
I use nodejs as backend
If you want to find all use findAll function with where.
const users = await storescors16.findAll({ id });
That if I understand you currect.
I am writing a multi-user online dictionary. I want to implement a leadership board, e.i. "score" attribute increases, as soon as a user adds a word. I have a rough idea on how to do it, and tried one solution, however it does not work. Could you please guide me?
Word API route
const express = require('express');
const router = express.Router();
const Word = require('../../models/Word');
const User = require('../../models/User');
const validateWordInput = require('../../validation/word');
const passport = require('passport');
// #route POST api/words
// #desc Add words to profile
// #access Private
router.post(
'/',
passport.authenticate('jwt', { session: false }),
(req, res) => {
const { errors, isValid } = validateWordInput(req.body);
// Check validation
if (!isValid) {
// Return any errors
return res.status(400).json(errors);
}
Word.find({}).then(word => {
if (
word.filter(
wrd =>
wrd.ugrWordCyr.toString().toLowerCase() ===
req.body.ugrWordCyr.toLowerCase()
).length !== 0
) {
return res
.status(404)
.json({ wordalreadyexists: 'Word already exists' });
} else {
const newWord = new Word({
user: req.user.id,
ugrWordCyr: req.body.ugrWordCyr,
rusTranslation: req.body.rusTranslation,
example: req.body.example,
exampleTranslation: req.body.exampleTranslation,
origin: req.body.origin,
sphere: req.body.sphere,
lexis: req.body.lexis,
grammar: req.body.grammar,
partOfSpeech: req.body.partOfSpeech,
style: req.body.style
});
newWord.save().then(word => res.json(word));
User.update(
{ _id: '5cf0cb78b3105d1ba8e30331' },
{ $inc: { score: 1 } }
);
}
});
}
);
User model
This is where a score attribute is located
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
// Create schema
const userSchema = new Schema({
name: {
type: String,
required: true
},
email: {
type: String,
required: true
},
password: {
type: String,
required: true
},
score: {
type: Number,
default: 0
},
avatar: {
type: String
},
date: {
type: Date,
default: Date.now
}
});
module.exports = User = mongoose.model('users', userSchema);
After successfully saving the word, we should update the user count
To update the respective user's score you can do the following:
newWord.save().then((word) => {
//now update user model
User.findOne({ _id: req.user.id }) <-- or an id you would like
.then((foundUser) => {
foundUser.score = foundUser.score + 1
foundUser.save()
.then((savedUser) => {
res.json({ word, savedUser })
})
.catch((err) => {
return res.status(400).json({ error: "could not add score"})
})
})
.catch((err) => {
return res.status(400).json({ error: "could not find user"})
})
})