Mongoose find not executing - javascript

Here's what I've got in a file called Zone.js,
var mongoose = require('mongoose');
mongoose.set('debug', true);
var zoneSchema = new mongoose.Schema({
name: {type: String, required: true, default: '', required: true},
timestamp: {type: Date, default: Date.now, required: true},
zipCodes: {type: [String], default: [], required: true}
});
module.exports = mongoose.model('Zone', zoneSchema);
And then here's what I've got in a file called zoneController.js,
var Zone = require('../models/Zone');
module.exports = {
find: function(params, callback){
console.log('Finding zone');
Zone.find(params, function(err, zones){
console.log('Got results');
if (err){
callback(err, null);
return;
}
callback(null, zones);
});
}
}
And then, I have,
ZoneController = require('../controllers/zoneController');
ZoneController.find({}, function(err, results){
console.log('Zone results received');
}
The problem is that the .find() method doesn't give me anything. I get 'Finding zone' in my console, but absolutely nothing after that.
My folder structure is correct and I am referencing the correct files.

try this, I think that you must to return your find method in your controller.
let me know if it work.
module.exports = {
return {
find: function(params, callback) {
console.log('Finding zone');
Zone.find(params, function(err, zones) {
console.log('Got results');
if (err) {
callback(err, null);
return;
}
callback(null, zones);
});
}
}
}

Here is a .find example for Tweet model in one of my old projects.
Tweet.find({}).sort({date: -1}).populate('_creator').exec((err, tweets) => {
res.render('tweet-all', {title: `All Tweets`, tweets: tweets});
});
I think you must use .exec() in Model.

Related

MongoDB/mongoose - Post save hook not running

I have this model/schema:
const InviteSchema = new Schema({
inviter: {type: mongoose.Schema.Types.ObjectId, ref: 'Account', required: true},
organisation: {type: mongoose.Schema.Types.ObjectId, ref: 'Organisation', required: true},
sentTo: {type: mongoose.Schema.Types.ObjectId, ref: 'Account', required: true},
createdAt: {type: Date, default: new Date(), required: true}
});
InviteSchema.post('save', function(err, doc, next) {
// This callback doesn't run
});
const Invite = mongoose.model('Invite', InviteSchema);
module.exports = Invite;
Helper function:
exports.sendInvites = (accountIds, invite, callback) => {
let resolvedRequests = 0;
accountIds.forEach((id, i, arr) => {
invite.sentTo = id;
const newInvite = new Invite(invite);
newInvite.save((err, res) => {
resolvedRequests++;
if (err) {
callback(err);
return;
}
if (resolvedRequests === arr.length) {
callback(err);
}
});
});
};
And the router endpoint which calls the helper function:
router.put('/organisations/:id', auth.verifyToken, (req, res, next) => {
const organisation = Object.assign({}, req.body, {
updatedBy: req.decoded._doc._id,
updatedAt: new Date()
});
Organisation.findOneAndUpdate({_id: req.params.id}, organisation, {new: true}, (err, organisation) => {
if (err) {
return next(err);
}
invites.sendInvites(req.body.invites, {
inviter: req.decoded._doc._id,
organisation: organisation._id
}, (err) => {
if (err) {
return next(err);
}
res.json({
error: null,
data: organisation
});
});
});
});
The problem here is that the .post('save') hook doesn't run, despite following the instructions, i.e. using .save() on the model instead of .findOneAndUpdate for example. I've been digging for a while now but I cannot see what the problem here could be.
The Invite document(s) are saved to the database just fine so the hook should fire, but doesn't. Any ideas what could be wrong?
You can declare the post hook with different number of parameters. With 3 parameters you are treating errors, so your post hook will be called only when an error is raised.
But, if your hook has only 1 or 2 parameters, it is going to be executed on success. First parameter will be the document saved in the collection, and second one, if passed, is the next element.
For more information, check official doc: http://mongoosejs.com/docs/middleware.html
Hope it helps.

mongodb/mongoose aggregation that combine two table/collection

I am using mLab for database and mongoose in node js.I am using swagger which should not cause any problem. I have following schemas. when user request, I need to return movie and review together if (review = true) in query. One movie may have multiple reviews. first, I have to find all the movies in the database. when I find movies, I have to go through each of them, look for any reviews in another database and somehow attach them in movie. I need to return all the movies in one package because it will be used in getAll fucntion. No matter what I do it only returning movies without reviews.
var mongoose = require('mongoose');
var reviewSchema = new mongoose.Schema({
movie: {type: String, required: true},
reviewer: {type: String, required: true},
rating: {type: Number, required:true, min: 1, max: 5},
text: {type: String, required: true},
})
var movieSchema = new mongoose.Schema({
Title: {type: String, required: true, unique: true},
YearReleased: {type: Number, required: true},
Actors: [{
Name: {type: String, required: true}
}]
})
.
function getAll(req,res,next){
db.Movies.find({},function(err,movies){
if(err) throw {err:err};
if(req.swagger.params.review.value === false)
res.send({Movielist: movie});
else {
movies.forEach(function(movie, index){
db.Reviews.find({movie:movies[index].Title}, function (err, review) {
if(err) throw {err:err}
movies[index].Review = review // I am trying to populate each movie with reviews
});
});
res.send({Movielist: movies});
}
});
}
res.send is called before the db reviews result is received:
movies.forEach(function(movie, index){
// this call is asynchronous, res.send will run before the callback
db.Reviews.find({movie:movies[index].Title}, function (err, review) {
if(err) throw {err:err}
movies[index].Review = review // I am trying to populate each movie with reviews
});
});
res.send({Movielist: movies});
You can use promises to wait for the results. I'll give an example with async/await. Using promises without async/await is also an option.
async function getAll(req,res,next) {
try {
let movies = await getMovies();
res.send(movies);
} catch (err) {
console.log(err.stack);
}
}
async function getMovies () {
return new Promise(function (resolve, reject) {
db.Movies.find({},function(err,movies){
if(err) reject(err);
if(req.swagger.params.review.value === false)
resolve({Movielist: movie});
else {
movies.forEach(function(movie, index){
let review = await getReviews();
movies[index].Review = review
});
resolve({Movielist: movies});
}
});
});
}
async function getReviews (movie, index) {
return new Promise(function (resolve, reject) {
db.Reviews.find({movie:movies[index].Title}, function (err, review) {
if(err) reject({err:err});
resolve(review);
});
});
}
This could need some tweaks as I have not tested it. I hope it gives the general idea of how to fix the issue.
Without async/await you can call the promises and run ".then" to process the results. If you haven't used promises a few google searches should help understand how .then works.
First thank you #curtwphillips
however, I have found short way to do this. But for this to work, movie and review have to in same database as different collection. If you use different database, it doesn't work
function getAll(req,res,next) {
if (req.query.review === 'true') {
db.Movies.aggregate([
{
$lookup: {
from: "reviews",
localField: "Title",
foreignField: "movie",
as: "review"
}
}
], function (err, result) {
if (err) throw {err: err};
else {
res.send({Movielist: result});
}
});
}
else {
db.Movies.find({}, function (err, movies) {
if (err) throw {err: err};
res.send({Movielist: movies})
})
}
}

Node js aggregation and findone concept

I need to find the history of person1 deals..so in my getHistory module i have filtered all the deals in that person1's dealSchema , in acceptreject function i have used aggregation concept to filter the deals which have person1's _d in the accepted field. But the callback function acceptreject does not fetch the result it always results in []..anyone please findout the mistake i have done in this code..Thanks in advance
var acceptreject = function (userId, callback){//callback function for finding accepted deal
console.log("Aggregate:" +userId);
if(userId == null && userId == 'undefined'){
console.log("error fetching id");
res.send(new Response.respondWithData('failed','Invalid userId'));
return next();
}
User.aggregate([
{
$unwind: "$deals"
},
{
"$match":
{
"deals.accepted": userId
//"deals.rejected": id
}
},
{
$project:{
"shopName":"$deals.shopName",
"deal":"$deals.deal",
"price":"$deals.price",
"name":"$name"
}
}
],function (err, user){
console.log(user);
if (err){
callback (err);
}
console.log("Your accepted deal:"+ user);
// res.send(200,user);
callback(null, user);
})
}
exports.getHistory = function (req, res, next) {
var incomingUser = req.user;
var id = incomingUser._id;
User.findById(id,function (err, user){
console.log(user);
if (err) {
return next(new Response.respondWithData('failed','Cant find theuser'));
}
var dealObj = _.filter(user.deals);
acceptreject({
userId : id
},function(err, users){
if(err){
res.send(new restify.InternaError(err.message));
return next();
}
else{
console.log("final");
var final = {
accepteddeal: users,//it returns [] in result but person1 accepted the deal
mydeal: dealObj
}
next(res.send(200, final));
}
});
});
}
And my schema is
var dealSchema = new mongoose.Schema({
shopName: {type: String,required: true},
deal: {type: String,required: true},
price:{type: Number,required: true},
start:{type: Date,default: Date.now},
end:{type: Date},
expiry:{type: Date},
comments:{type: String},
accepted: {type:mongoose.Schema.Types.ObjectId, ref:'user'},//person1 _id
rejected: {type:mongoose.Schema.Types.ObjectId, ref: 'user'}
});
var userSchema = new mongoose.Schema({
name: { type: String,required: true},
phone: { type: Number, required: true,unique: true},
email:{type: String},
password: {type: String},
deals:[dealSchema]
}, {collection: 'user'});
mongoose.model('Deal', dealSchema);
mongoose.model('user', userSchema);
I have done a mistake in callback function where the userId parameter of that function does not pass the id
var accept= function (userId, callback){
console.log("Aggregate:" +userId);
if(userId == null && userId == 'undefined'){
res.send(new Response.respondWithData('failed','Invalid userId'));
return next();
}
var id = new Object(userId);
console.log(id);
User.aggregate([
{
$unwind: "$deals"
},
{
"$match": {
"deals.accepted" : id
}
},
{
$project:{
"shopName":"$deals.shopName",
"deal":"$deals.deal",
"price":"$deals.price",
"name":"$name"
}
}
],function (err, user){
console.log(user);
if (err){
callback(err);
}
console.log("Your accepted deal:"+ user);
//res.send(200,user);
callback(null, user);
})
}

mongoose setting referenceone

Hello can someone help me. I can't set mongoose model field
Here my institute.js model file
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var instituteSchema = new Schema({
name: {type: String, required: true},
idApi: {type: String, required: true},
country: {
type: Schema.ObjectId,
ref: 'Country'
},
created_at: {type: Date, default: Date.now}
}, {collection: 'qel_par_institute', versionKey: false});
instituteSchema.methods.findByIdApi = function (id, callback) {
return mongoose.model('Institute').findOne().where('idApi').equals(id).exec(callback);
}
instituteSchema.methods.findByCountry = function (id, callback) {
return mongoose.model('Institute').find().where('country.id').equals(id).exec(callback);
}
mongoose.model('Institute', instituteSchema);
There the part of sync.js Persisting works except i can't either manually set the country ref neither another field
var instituteApi = new instituteModel({
name: item.name,
idFromApi: item.id
});
if (typeof item.country.id !== 'undefined') {
var country = new countryModel();
country.findByIdApi(item.country.id, function(err, res) {
if (err)
console.log(err);
if (res) {
instituteApi.country = res._id; //setting this way doesn't work
}
})
}
instituteApi.save(function(err) {
if (err)
console.log('something went wrong while saving!');
});
Couldn't set it because async call. Switched callback to promise with Q module. Everything works as wanted

findByIdAndUpdate $set does not check for unique?

I have a schema and specify login is unique is true. When I use findByIdAndUpdate and pass query $set to update an user object, it did not throw back error when login is dup. Does anyone know why and how I should update an object and force schema validation?
Thanks!
// UserSchema.js
var schema = new Schema({
login: {
required: true,
unique: true
},
password: {
index: true,
type: String
}
});
// Update
UserSchema.findByIdAndUpdate('someID', { '$set': { login: 'abc' } }, function (error, user) {
callback(error, user);
});
You simply need to set runValidators to true:
findByIdAndUpdate(req.params.id, {$set: data}, {runValidators: true}, function (err, doc) {
if (err) {
// Handle validation errors
}
})
More here: http://mongoosejs.com/docs/api.html#findOneAndUpdate
Using the shorthand helper methods in Mongoose bypasses validation, so you need to use a 3 step approach:
Find
Edit
Save
For example:
// 1: Find
UserSchema.findById( 'someID',
function (err, user) {
if(!err){
// 2: Edit
user.login = 'abc';
// 3: Save
user.save(function (err, user) {
if (err) {
console.log(err);
return;
}
console.log('User saved: ' + user);
});
}
}
);

Categories

Resources