I am quite new to node.js and I am writing a GET request to retrieve documents from my database. Here is the definition of my request (in users.js) -
router.get('/', function (req, res, next) {
Booking.find({} ,(err,prevBookings)=>{
if(err) {
res.status(400).send('No previous bookings found.');
}
if(prevBookings[0]) {
res.status(200).send(prevBookings);
}
else{
console.log("no records")
res.status(200).send("No previous bookings found.")
}
});
});
And I have defined these in the index.js file as follows:
router.use('/users', require('./users'))
router.use('/prev', require('./users'))
//and there are other routers here too but totally unrelated to users.js
But, I am getting the following error on Postman:
NotFoundError: Not Found
I know that this error indicates that I am not routing it correctly. But I am not able to identify where I am going wrong. Other routes that I have defined, are working. Could anyone please help me out with this? Thank you :)
I think you're specifying '/prev' twice. If you change your route in users.js to "/", see what happens. I think at the moment the route "/prev/prev" will return a result.
I'm guessing your users.js should look like so:
const express = require("express");
const router = express.Router();
router.get('/', function (req, res, next) {
Booking.find({} ,(err,prevBookings)=>{
if(err) {
res.status(400).send('No previous bookingd found.');
}
if(prevBookings[0]) {
res.status(200).send(prevBookings);
}
else{
console.log("no records")
res.status(200).send("No previous bookings found.")
}
});
});
module.exports = router;
And then at the top level (index.js) or whatever:
app.use("/", router);
router.use('/prev', require('./users'))
This should return the correct result on "/prev"
For the booking model, could you try modifying the mongoose schema like so (adding the { collection: } entry):
var bookingSchema = mongoose.Schema({
_id : {
type: mongoose.Schema.Types.ObjectId,
required: true
},
user_id : {
type: mongoose.Schema.Types.Mixed,
ref: 'User',
required: true
},
places_id : {
type: mongoose.Schema.Types.ObjectId,
ref: 'Place',
required: true
},
fromDate : {
type: Date,
required: true,
default: Date.now()
},
toDate : {
type: Date,
required: true,
default: Date.now()
},
people_count : {
type: String,
required: true
},
package_details : {
type: mongoose.Schema.Types.Mixed
},
total_cost : {
type : Number,
required : true
},
cost : {
type: Number,
required: true
},
// confirmation: {
// type : String,
// required: true
// },
transaction_no : {
type : String,
required : true
}
}, {
collection: 'booking'
}
)
Related
I've been on this problem for quite a while. I have 2 schemas:
**The User Schema**
const mongoose = require('mongoose');
const PaymentSchema = require('../models/payments').schema;
const UserSchema = new mongoose.Schema({
firstname :{
type : String,
required : true
} ,
lastname :{
type : String,
required : true
} ,
email :{
type : String,
required : true
} ,
country :{
type : String,
required : true
} ,
state :{
type : String,
required : true
} ,
city :{
type : String,
required : true
} ,
postal :{
type : String,
required : true
} ,
phone :{
type : String,
required : true
} ,
plan :{
type : String,
} ,
amount :{
type : String,
} ,
profit:{
type: String,
},
amountDue:{
type: String,
},
password :{
type : String,
required : true
} ,
withdrawals :[PaymentSchema],
payDate :{
type : Date,
default : Date.now
},
date :{
type : Date,
default : Date.now
}
});
const User= mongoose.model('User', UserSchema);
module.exports = User;
The payments Schema
const mongoose = require('mongoose');
const PaymentSchema = new mongoose.Schema({
firstname: {
type: String
},
lastname:{
type: String
},
balance:{
type: String
},
address: {
type: String,
required: true
},
amount: {
type: Number,
required: true
},
paid: {
type: Boolean,
required: true
},
userid:{
type: String
},
date: {
type: Date,
default: Date.now
}
});
const Payment = mongoose.model('Payment', PaymentSchema);
module.exports = Payment;
The logic is this: When a user makes payment, a POST request is sent and the information from the payment request is displayed on an admin dashboard. The POST request looks like this:
router.post('/users/:id/payments', function (req, res) {
User.findById(req.params.id, function (err, fuser) {
if (err) {
req.flash('error_msg', 'Something went wrong. Please login and try again')
res.redirect('/logout')
} else {
var pay = new Payment({
firstname: fuser.firstname,
lastname: fuser.lastname,
balance: fuser.amount,
amount: req.body.usd,
address: req.body.to,
paid: false,
userid: fuser.id
})
pay.save(function (err, pays) {
if (err) {
console.log(err)
} else {
User.findById(req.params.id, function (err, userr) {
userr.withdrawals.push(pays)
userr.save(function (err, user) {
if (err) {
req.flash('error_msg', 'Something went wrong. Please login and try again')
res.redirect('/logout')
} else {
res.redirect('/dashboard')
}
})
})
}
})
}
})
The information sent to the admin dashboard is then approved and the admin makes a PUT request to that particular payment, updating the "paid" property to "true". Like so:
router.put('/admin/withdrawals/:id', function (req, res) {
var update = {
paid: true
}
Payment.findByIdAndUpdate(req.params.id, update, function (err, user) {
if (err) {
res.send("error!")
} else {
User.findById(user.userid, function (err, uza) {
if (err) {
res.send("error!")
} else {
var amount = uza.amount
var deduct = req.body.aamount
var balance = parseInt(amount) - parseInt(deduct)
var updated = {
amount: balance,
}
User.findByIdAndUpdate(user.userid, updated, function (err, pays) {
if (err) {
res.send(err)
} else {
req.flash('success_msg', 'Withdrawal has been confirmed!')
res.redirect('/admin/dashboard')
}
})
}
})
}
})
})
The payment document gets updated to "true" but the embedded payment document on the User Schema still remains "false".
Please what do I need to do to update the paid property from "false" to "true" on both the main payment document and on the embedded payment document?
You need to link between the schemas like so:
withdrawals: [{ type: Schema.Types.ObjectId, ref: 'Payment' }],
Otherwise you have to update the data in both schemas manually!
See the docs here: https://mongoosejs.com/docs/api.html#schematype_SchemaType-ref
I have been looking at the documentation and some other questions made, but I have not been able to do it, I need to consult another collection for an objectId, but these collections come dynamically in the routes.
The collections come req, as they are from many different clients
https://mongoosejs.com/docs/populate.html
//route
// example collection dynamic ssdf2451_users, ssdf2451_campus, ssdf2451_programs
router.get('/school/prueba/tipos/', async (req, res, next) => {
let users
let school
let prueba
try {
const Users = model(`ssdf2451_users`, UserSchema)
console.log(Users)
await Users.findOne({ _id: '5ef56f70d19aea6e70c82a50' })
.populate('schoolId')
.exec(function (err, usersDocuments) {
console.log(usersDocuments, err)
// handle err
prueba = usersDocuments
res.status(200).json(prueba)
})
} catch (err) {
next(err)
}
})
// Schema
import { Schema, model } from 'mongoose'
const UserSchema = new Schema({
state: {
type: Boolean,
default: false,
required: false
},
accountNumber: {
type: Number,
required: false
},
schoolId: {
type: Schema.Types.ObjectID,
required: true,
ref: 'schools'
},
campusId: {
type: Schema.Types.ObjectID,
required: true,
ref: dynamic
},
programsId: {
type: [Schema.Types.ObjectID],
required: false,
ref: dynamic
},
})
const User = model('users', UserSchema)
export { User, UserSchema }
I am attempting to Model.find({}) all documents within a collection on two exactly similar express routes. On one of my routes, this happens no problem and all documents are returned. Yet, on a different express route with the exact same logic, I receive the following error:
Cast to ObjectId failed for value "featured" at path "_id" for model "Location"
Utilizing the mongo shell db.locations.find() I receive the documents no problem.
Here is my Schema for locations:
var mongoose = require('mongoose');
var { pointSchema } = require('../Geoschema-Types/GeoSchemas');
const LocationSchema = new mongoose.Schema({
name: {type: String, required: true},
PATH: [{type: mongoose.Schema.Types.ObjectId, ref: 'SOME_COLLECTION'}],
PATH: [{type: mongoose.Schema.Types.ObjectId, ref: 'SOME_COLLECTION'}],
PATH: String,
location: {
type: pointSchema,
required: true
},
settings: {
private: Boolean
},
meta: {
created: { type : Date, default: Date.now },
view_count: {type: Number, default: 0},
tags: [String],
likes: {type: Number, default: 0},
numberOfComments: {type: Number, default: 0},
numberOfShares: {type: Number, default: 0}
},
comments: [{type: mongoose.Schema.Types.ObjectId, ref: 'Comment'}],
typeoflocation: String
});
LocationSchema.query.nearPoint = function(coordinates, maxDistance) {
return this.where('location')
.near({ center: { coordinates, type: 'Point' }, maxDistance, spherical: true })
};
LocationSchema.options.autoIndex = true;
LocationSchema.index({ location: "2dsphere" });
var Location = mongoose.model("Location", LocationSchema);
module.exports = Location;
In my root file app.js I have both of the routes placed in middleware each with different parent paths for their respective routers.
app.use('/test', require('./tests/routes/Test-Routes'))
app.use('/locations', require('./routes/Models/Locations/Location-Routes'));
~ /Location-Routes ------------ FULL FILE
const express = require('express');
const router = express.Router();
const { isLoggedIn } = require('../../../util/middleware/auth-util')
const {
addCommentUtil,
LikePostUtil,
deletePostUtil
} = require('../../../util/middleware/post-actions-util');
const {
newLocation,
findNear,
viewLocation
} = require('../../../controllers/Models/Locations/Location-Controllers')
// MODEL
const Location = require('../../../models/Location/LocationSchema')
router.route('/findnear')
.post(findNear)
router.route('/:id')
.get(isLoggedIn, viewLocation)
router.route('/featured')
.get((req, res, next) => {
Location.find({})
.then(docs => {
res.send(docs)
})
.catch(next)
})
router.route('/newlocation')
.post(isLoggedIn, newLocation)
router.route('/:id/addcomment')
.post(isLoggedIn, addCommentUtil(Location));
router.route('/:id/like')
.post(isLoggedIn,LikePostUtil(Location))
// DELETE ---------------------------------------------------------
router.route('/:id/delete')
.delete(isLoggedIn, deletePostUtil(Location))
module.exports = router;
~ /Test-Routes
router.route('/featured')
.get((req, res, next) => {
Location.find({})
.then(docs => {
res.send(docs)
})
.catch(next)
})
All other routes on the ~/Locations router work just fine, including adding documents and deleting them... yet this one query returns the above error:
Cast to ObjectId failed for value "featured" at path "_id" for model "Location"
Using the ~/Test-Routes route works just fine.
Because you put router.route('/:id') before router.route('/featured') so when you call to /featured, it will recognize featured as :id and go to your viewLocation function in your Location-Controllers.
Changing your route to put router.route('/featured') before router.route('/:id') may solve the problem.
I have a Torrent item, it has subdocument array named '_replies' to saved user comments, and every comment also include subdocument array '_replies' to saved user reply, this is my all schema define:
var CommentSchema = new Schema({
user: {
type: Schema.Types.ObjectId,
ref: 'User'
},
comment: {
type: String,
default: '',
trim: true
},
_replies: [this],
createdat: {
type: Date,
default: Date.now
},
editedby: {
type: String,
default: '',
trim: true
},
editedat: {
type: Date,
default: ''
}
});
var TorrentSchema = new Schema({
user: {
type: Schema.Types.ObjectId,
ref: 'User'
},
torrent_filename: {
type: String,
default: '',
trim: true,
required: 'filename cannot be blank'
},
torrent_title: {
type: String,
default: '',
trim: true,
required: 'title cannot be blank'
},
_replies: [CommentSchema]
});
mongoose.model('Torrent', TorrentSchema);
mongoose.model('Comment', CommentSchema);
the first level comment of torrent update/delete fine, the code of server controller likes below:
exports.update = function (req, res) {
var torrent = req.torrent;
torrent._replies.forEach(function (r) {
if (r._id.equals(req.params.commentId)) {
r.comment = req.body.comment;
r.editedat = Date.now();
r.editedby = req.user.displayName;
torrent.save(function (err) {
if (err) {
return res.status(422).send({
message: errorHandler.getErrorMessage(err)
});
} else {
res.json(torrent); //return data is Correct, and save to mongo is Correct
}
});
}
});
};
but when i used Alike function to update/delete _replies._replies, it can return Correct json of torrent to response, Unfortunate, the save to mongo not fine, the code:
exports.SubUpdate = function (req, res) {
var torrent = req.torrent;
torrent._replies.forEach(function (r) {
if (r._id.equals(req.params.commentId)) {
r._replies.forEach(function (s) {
if (s._id.equals(req.params.subCommentId)) {
s.comment = req.body.comment;
s.editedat = Date.now();
s.editedby = req.user.displayName;
torrent.save(function (err) {
if (err) {
return res.status(422).send({
message: errorHandler.getErrorMessage(err)
});
} else {
res.json(torrent);//return data is Correct, but save to mongo is incorrect
}
});
}
});
}
});
};
also, i can delete first level comment, but can not delete second level comment reply, all the json data of torrent is correct, only not save to mongo.
what can i do more?
I already solve it, i add this code before .save().
torrent.markModified('_replies');
it work fine!
I have built a mean app but am having an issue with it posting a number value. I'm not sure if it is a mongoose validation error but for some reason mongoose can not upsert the number value but will when it is a string.
Here's the route:
//Edit A Site
router.put('/api/sites/:site_id', function(req, res) {
Site.findById(req.params.site_id, function(err, site) {
if (err) {
res.send(err);
} else {
if(req.body.ip) site.ip = req.body.ip;
if(req.body.domain) site.domain = req.body.domain;
if(req.body.wp) site.wp = req.body.wp;
if(req.body.host_name) site.host_name = req.body.host_name;
if(req.body.hosted) site.hosted = req.body.hosted;
console.log(req.body);
// save the site
site.save(function(err) {
if (err)
res.send(err);
res.json(site);
});
}
});
});
The console.log has the full request body:
{ hosted: 1, host_name: 'sup', wp: 'n/a' }
But this is the mongoose response: Mongoose: sites.update({ _id: ObjectId("57a16c4a7f7e5b7a7e1f5ad1") }, { '$set': { host_name: 'sup', wp: 'n/a' } })
Schema:
// grab the things we need
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
// create a schema
var sitesEntrySchema = new Schema({
ip: {
type: String,
required: true,
trim: true
},
domain: {
type: String,
required: true,
trim: true
},
wp: {
type: String,
required: true,
trim: true
},
host_name: {
type: String,
required: true
},
hosted: {
type: Number,
min: 0,
max: 1,
required: true
}
});
// make this available to our users in our Node applications
var Site = mongoose.model('Site', sitesEntrySchema);
module.exports = Site;
EDIT:
I believe I found the solution. When checking for the req.body.hosted, because it is a number it fails. I had to update to check for undefined:
if(req.body.hosted != undefined) site.hosted = req.body.hosted;