I have a node.js website. I am using mongoose to connect with my mongodb. Adding new records works fine and find also works fine.
But when I update the record it throws the error below. I have a callback function but dont know whats wrong.
throw new Error("writeConcern requires callback")
^
Error: writeConcern requires callback
Below is my update code.
var newUser = new User();
newUser.update({ 'local.email' : emailID }, { 'local.resetkey': ResetHash }, { multi: false }, function (err, res) {
if (err) return handleError(err);
console.log('The raw response from Mongo was ', raw);
});
This is my schema...
var mongoose = require('mongoose');
var bcrypt = require('bcrypt-nodejs');
var crypto = require('crypto');
var safe = { w: "0" };
// define the schema for our user model
local : {
email : String,
password : String,
resetkey : String,
resetexpiry : String,
},
});
module.exports = mongoose.model('User', userSchema);
newUser is a document, but you are calling update as it is defined for the model and therefore getting a wrong argument in place of the callback
Try: User.update(... as in the mongoose API docs: Model.update(conditions, update, options, callback);
You show incomplete code for your schema.
Related
I trying to update a field in users collection once a user is logged into the application. But the update query is not working at all.
users.js
var express = require('express');
var router = express.Router();
var User = require('../models/user');
var jwt = require('jsonwebtoken');
router.post('/login', function(req,res,next){
let promise = User.findOne({email:req.body.email}).exec();
promise.then(function(doc){
if(doc) {
if(doc.isValid(req.body.password)){
// generate token
let token = jwt.sign({username:doc.username},'secret', {expiresIn : '3h'});
setOnlineStatus(doc.username);
} else {
return res.status(501).json({message:' Invalid Credentials'});
}
} else {
return res.status(501).json({message:'User email is not registered.'})
}
});
promise.catch(function(err){
return res.status(501).json({message:'Some internal error'});
})
})
function setOnlineStatus(username){
console.log(username); // log the correct username value
User.update(
{'username': username},
{$set: {'status':'Online'}},
);
}
Model - user.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var bcrypt = require('bcrypt');
var schema = new Schema({
email : {type:String, require:true},
username: {type:String, require:true},
password:{type:String, require:true},
creation_dt:{type:Date, require:true}
});
schema.methods.isValid = function(hashedpassword){
return bcrypt.compareSync(hashedpassword, this.password);
}
module.exports = mongoose.model('User',schema);
So now the problem is once a request is send to /login service, the call to setOnlineStatus() is not updating users collection with a new field status having value 'online'.
NOTE: Using another service /register users are already added to the users collection.
I'm a newbie to express and mongodb. So please help me to solve this issue.
Thank you and answers will be appreciated.
you need to define status in the schema as mongoose will ignore it while updating other wise (read: option: strict)
try adding status: {type: String} to your schema
also the update() function returns a query (read: Model.update()) it doesn't update unless you pass a callback or execute it with .exec()
User.update({'username': username}, {$set: {'status':'Online'}}).exec()
I have already seen the discussion about the following question with a similar title
mongoose 'findById' returns null with valid id
But my problem is not the database name since all my other connections with the same database in fact the queries on the same collection are working fine.
I am using mongoose 4.13.6, node js 6.11 and mongo 3.4.
It is a post request .
var query=req.body;
I am sending the search parameters as
var findFruit =
{
_id:query._id
}
When I print my findFruit I get :
_id:'5a1cf77920701c1f0aafb85e'
The controller function for this is :
Fruit.findById(findFruit._id,function(err,fruit){
if( _.isNull(err) ){
var response = genRes.generateResponse(true,"found successfully");
callback(response);
}
else{
var response = genRes.generateResponse(false,"there occured some error : "+err);
callback(response);
}
})
I even tried find
Fruit.find(findFruit,function(err,fruit){
if( _.isNull(err) ){
var response = genRes.generateResponse(true,"found successfully");
callback(response);
}
else{
var response = genRes.generateResponse(false,"there occured some error : "+err);
callback(response);
}
})
The collection for sure has the entry under this id .
I went through this git issue as well https://github.com/Automattic/mongoose/issues/3079
Unfortunately I cannot downgrade mongoose as it might affect multiple other working functions.
Edit :
I tried creating ObjectId like :
var mongoose = require('mongoose');
var ObjectID = require('mongodb').ObjectID;
var objectId = new ObjectID();
// Convert the object id to a hex string
var originalHex = objectId.toHexString();
// Create a new ObjectID using the createFromHexString function
var newObjectId = new ObjectID.createFromHexString(query._id);
The model file :
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var ObjectId = Schema.ObjectId;
var FruitSchema = new Schema({
name : {type : String, unique : true},
color : {type : String}
});
module.exports = mongoose.model('Fruit', FruitSchema);
All my findById("id") calls returned null.
When looking at the collection with Compass I realized that all my _id elements were Strings. Note that the entire collection was imported.
I created a new element in Compass and the _id was created as ObjectId! and when I called findById("id") with that element's id it worked!
My conclusion is that there is obviously a bug with import. I have not found a way to convert the string _id fields to ObjectId's in the actual collection.
All my findById("id") calls returned null, when _id elements are Strings.
In the first place:
Check your mongodb database, if _id is stored as String, findById(id) can not find since it identifies ObjectId. If you've used import database by using mongoimport command and including _id in JSON:
Solution 1:
modify your JSON and for each document, change _id for instance:
_id: "5a68fde3f09ad7646ddec17e" to the following and run mongoimport again:
"_id": { "$oid": "5a68fde3f09ad7646ddec17e" }
Solution 2:
delete _id in the JSON file, drop collection and import again. Mongo will auto-create _id.
After any of solutions above, findById("id") will work.
Secondly:
Specifically in such cases where your _id elements are string, might be a better idea to use mongodb package: npm i mongodb
var MongoClient = require('mongodb').MongoClient;
var url = "mongodb://localhost:27017/";
MongoClient.connect(url, function (err, db) {
if (err) throw err;
var dbo = db.db("your_db_name");
dbo.collection("fruits_collection")
.find({_id:'5a1cf77920701c1f0aafb85e'})
//.find({_id:'5a1cf77920701c1f0aafb85e'}, { projection: { _id: 0, name: 1, color: 1} }) // to select specific columns desired
.toArray(function (err, result) {
if (err) throw err;
console.log(result);
db.close();
});
});
The above simple code, assumed you manage error handling yourself, either through try-catch, or
sending 404 as status code, or redirect to error page template, depending on whether the code is embedded in the Express route handler or not.
Hope this helped .. :)
Still trying to figure out why findById didn't work for me but the following piece of code did it
var mongoose = require('mongoose');
var newObjectId=new mongoose.Types.ObjectId(query._id);
var params={
'_id':newObjectId
}
Fruit.find(params).exec(function (err,fruit) {
if( _.isNull(err) ){
var response = genRes.generateResponse(true,"found successfully");
callback(response);
}
else{
var response = genRes.generateResponse(false,"there occured some error : "+err);
callback(response);
}
})
#Shoom. Yes, worked for me, thanks. findById() expects ObjectID, not a String.
I did not have a constraint to create documents with a specific id, so I imported with no _id. The db had newly-assigned _id as ObjectID.
findById(id), (and updateOne({ _id: id }, ...), started working as expected.
I'm desperately trying to solve my problem with "find" queries with mongoose in my app.
I begin to know very well the middleware, I used it on others apps and work well, but on a new project something goes wrong and it only finds null objects in my database...
//server/app.js
var db = require('./lib/database');
var User = require('./models/user');
//server/lib/database.js
var mongoose = require('mongoose');
var db = function () {
mongoose.connect('mongodb://localhost/pipeline');
var connection = mongoose.connection;
connection.on('error', console.error.bind(console, 'connection error'));
connection.once('open', function callback() {
console.log('connected'); //result : connected
});
};
module.exports = db();
//server/models/user.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var userSchema = new Schema({ username: String, password: String });
module.exports = mongoose.model('User', userSchema);
Mongoose is well connected, there's no error in the console. So when mongoose is connected I use this method (I precisely use this in my LocalStrategy for PassportJS) :
User.findOne({username: "Paul"}, function (err, user){
console.log(user); // result : null
});
It's always null (and no error during the query), I also tested find({}) to check all entries, but the result is an empty array [].
Here's the User collection of my pipeline database (checked with Robomongo):
/* 0 */
{
"_id" : ObjectId("547649df8d99c22fa995b050"),
"username" : "Paul",
"password" : "test"
}
/* 1 */
{
"_id" : ObjectId("54765efdcd3b13c80c2d03e2"),
"username" : "Micka",
"password" : "lol"
}
Thank you for your help.
To have the 'User' model use the User collection, you need to explicitly provide that collection name as the third parameter to mongoose.model, otherwise Mongoose will use the pluralized, lower-cased model name which would be users.
module.exports = mongoose.model('User', userSchema, 'User');
I'm new to mongoose and I'm having a hard time finding the issue within my code. I'm building a REST server using Sails.js and Mongoose. I have a node module (e.g. "sails-mongoose") for exporting mongoose, where I also connect to my database:
var mongoose = require('mongoose');
mongoose.connect('mongodb://#localhost:27017/fooria');
module.exports = mongoose;
And in my model.js:
var adapter = require('sails-mongoose');
var schema = new adapter.Schema({
firstname: {
type: String,
required: true,
trim: true
}
});
module.exports = {
schema: schema,
model: adapter.model('Collection', schema)
}
In my controller's create method I have:
create: function(req, res, next) {
var userData = {firstname: 'Test'};
var users = new Users.model(userData);
users.save(function(err, data){
if (err) return res.json(err, 400);
res.json(data, 201);
});
}
When running create method, the entry is saved to the Mongodb collection but the callback is never reached. Can someone please help me on this track, as I found similar questions but none helped me though. Thanks!
I suppose your are using Express. According Express docs you are calling res.json using incorrect parameters (wrong order).
Correct format:
res.json(code, data)
Example:
res.json(500, { error: 'message' })
Windows 7 x64, node.js, mongoose from npm.
var sys = require('util');
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost:28960/test_mongoose');
var Schema = mongoose.Schema;
//Model
var UserSchema = new Schema({
username : String,
uid : String,
messaged_on : Date
});
mongoose.model('User', UserSchema);
var User = mongoose.model('User');
// create a new user
var user = new User({
uid : '54321',
username : 'Bob',
messaged_on : Date.now()
});
user.save( function (err) {
if (err)
return;
console.log('Saved');
User.find().all(function(user) {
console.log('beep');
});
});
Connection to mongod accepted, database 'test_mongoose' created.
Console print 'Saved', but 'beep' not.
I am newbie in mongoose, but, what is a prolem? Why do User.find().add() not call function back (user)?
Sorry for my bad english.
Maybe is it normal?
You should be calling User.find(... instead of User.find().all(.... The all method invokes the $all operator which is only used when matching arrays.