I have a custom validation when I upload an image to mongoDb. The original name should be unique. If it passes the validation, the code runs properly. But if it fails, it produces error. It says that custom validators that take 2 arguments) are deprecated in mongoose >= 4.9.0. Is there another way to validate the uniqueness of the originalname? Or a way to catch the error? Please help.
router.post('/upload',function(req,res){
Item.schema.path('originalname').validate(function(value, done) {
Item.findOne({originalname: value}, function(err, name) {
if (err) return done(false);
if (name) return done(false);
done(true);
});
});
upload(req,res,function(err, file) {
if(err){
throw err;
}
else{
var path = req.file.path;
var originalname = req.file.originalname;
var username = req.body.username;
var newItem = new Item({
username: username,
path: path,
originalname: originalname
});
Item.createItem(newItem, function(err, item){
if(err) throw err;
console.log(item);
});
console.error('saved img to mongo');
req.flash('success_msg', 'File uploaded');
res.redirect('/users/welcome');
}
});
});
model
var ItemSchema = mongoose.Schema({
username: {
type: String,
index: true
},
path: {
type: String
},
originalname: {
type: String
}
});
var Item = module.exports = mongoose.model('Item',ItemSchema);
module.exports.createItem = function(newItem, callback){
newItem.save(callback);
}
you can provide uniqueness to that field like :-
var ItemSchema = mongoose.Schema({
username: {
type: String,
index: true
},
path: {
type: String
},
originalname: {
type: String,
unique:true // this string will be unique all over the database
}
});
var Item = module.exports = mongoose.model('Item',ItemSchema);
module.exports.createItem = function(newItem, callback){
newItem.save(callback);
}
To validate uniqueness before saving to db, you can try to findOne with tour filename:
router.post('/upload',function(req,res){
Item.findOne({originalname: req.file.originalname}, function(err, name) {
if (err) return done(false); // errors
if (name) return done(false); // check for existence of item here
done(true);
});
});
If findOne function did not respond with any data, it means that, there is no document in collection with the same original name, and you can proceed with adding document to collection
Related
I have a collection called Users which stores user's messages & info. I want to add new objects to existing collection by it's id.
I receive an error 'TypeError: user.insert is not a function' - i guess i missed something....
Here is the method from the controller :
UserDataController.prototype.sendMsg = function (userID, messages_data, cb) {
if (userID) {
user.findOne({_id: userID},function(err, result){ //Object id=59e5e542a5ba05056c57d847
// insert to the collection with the object id
user.insert({_id: userID} ,messages_data,function(err, result){
if(err) return cb(err);
return cb(null, result);
});
});
}
};
Here is the result i wish to get :
"sentmessages" : [{
"message_body" : "whatsup", // new object
"message_subject" : "whatsup",
"message_date" : "20/01/2017"
},
{
"message_body" : "whatsup", // new object
"message_subject" : "whatsup",
"message_date" : "20/01/2017"
}]
The schema looks like that :
var sentmessages = new schema({
message_date: String,
message_subject : String,
message_body : String,
});
var UserSchema = new schema({
firstname: String,
lastname: String,
email: String,
sentmessages :[sentmessages] // here is were i want to add new objects
});
Got it... needed to use $push
UserDataController.prototype.sendMsg = function (userID, messages_data, cb)
{
if (userID) {
var message_fixesd_data = messages_data.sent_messages[0];
user.update({_id: userID},
{ $push: { sent_messages: {
message_body : message_fixesd_data.message_body,
message_subject: message_fixesd_data.message_subject,
message_date : message_fixesd_data.message_date
}
}
}, function (err, result) {
if(err)
{
return cb(err);
}
else
{
return cb(true, 'File was save successfully', result);
}
});
}
};
I have 2 collections called User and Location. In User, there is a location _id and this is an Object. Id also references the location collection. My question is what did I do wrong? When I call getUser function I want to see user information and the user's location information. What I need to do ?
User Schema
module.exports = (function userSchema() {
var Mongoose = require('mongoose');
var userSchema = Mongoose.Schema({
name: {
type: String,
require: true
},
surname: {
type: String,
require: true
},
tel: {
type: String,
require: true
},
age: {
type: String,
require: true
},
mevki_id: {
type: String,
require: true
},
location_id: [{
type: Mongoose.Schema.Types.ObjectId,
ref: 'locations'
}]
});
var collectionName = 'users';
var User = Mongoose.model(collectionName, userSchema);
return User;
})();
User Controller
function userController() {
var User = require('../models/UserSchema');
this.createUser = function (req, res, next) {
var name = req.body.name;
var surname = req.body.surname;
var tel = req.body.tel;
var age = req.body.age;
var mevki_id = req.body.mevki_id;
var lok_id = req.body.lok_id;
User.create({
name: name,
surname: surname,
tel: tel,
age: age,
mevki_id: mevki_id,
lok_id: lok_id
}, function (err, result) {
if (err) {
console.log(err);
return res.send({
'error': err
});
} else {
return res.send({
'result': result,
'status': 'successfully saved'
});
}
});
};
this.getUser = function (req, res, next) {
User.find()
.populate('lok_id')
.exec(function (err, result) {
if (err) {
console.log(err);
return res.send({
'error': err
});
} else {
return res.send({
'USERS': result
});
}
});
};
return this;
};
module.exports = new UserController();
First, your schema is wrong:
var userSchema = new Mongoose.Schema({
// ...
location_id: { type: [Mongoose.Schema.Types.ObjectId], ref: 'locations' }
})
Second, in your schema the last field name is location_id while in your controller, you change it to lok_id.
So, fix this:
User.create({
// ...
location_id: lok_id
}
and this:
User
.find()
.populate('location_id')
UPDATE
In your json the last field name is location_id, therefore, fix this too:
this.createUser = function (req, res, next) {
// ...
var lok_id = req.body.location_id;
}
I have one schema defined in userref.js
module.exports = (function userref() {
var Schema = mongoose.Schema;
var newSchema= new Schema([{
userId: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
index: true
},
value: { type: Number }
}]);
var results = mongoose.model('UserRef', newSchema);
return results;
})();
I have inserted some data and when I try to fetch some data I am getting proper values from mongodb console
db.getCollection('userrefs').find({'userId':ObjectId('57a48fa57429b91000e224a6')})
It returns properly some data
Now issue is that when I try to fetch some data in code by giving objectId I am getting empty array. In below function userrefs is returned as empty array
//req.params.userId=57a48fa57429b91000e224a6
var UserRef = require('../userref.js');
this.getuserref = function (req, res, next) {
try {
var o_userId =mongoose.Types.ObjectId(req.params.userId);
var query = { userId: o_userId };
var projection = '_id userId value';
UserRef.find(query, projection, function (err, usrrefs) {
if (err) return next(err);
res.send(usrrefs);
console.log("userref fetched Properly");
});
} catch (err) {
console.log('Error While Fetching ' + err);
return next(err);
}
};
Also when I debug code I can see o_userId as objectId with id value as some junk character
o_userId: ObjectID
_bsontype: "ObjectID"
id: "W¤¥t)¹â$¦"
Try this:
try {
var o_userId =mongoose.Types.ObjectId(req.params.userId);
var query = { userId: o_userId };
var projection = '_id $.userId $.value';
UserRef.find(query, projection, function (err, usrrefs) {
if (err) return next(err);
res.send(usrrefs);
console.log("userref fetched Properly");
});
} catch (err) {
console.log('Error While Fetching ' + err);
return next(err);
}
Add the export like this
module.exports.modelname= mongoose.model('userrefs', nameofschema, 'userrefs');
var z = require('../userref.js');
var UserRef = z.modelname;
Now call using UserRef.
Just simply try this man.
Model.find({ 'userId': objectidvariable}, '_id userid etc', function (err, docs) {
// docs is an array
});
Reference sample copied from their official doc.
I'm having a problem saving items running through for loop if I attach any extra validation methods. Basically, I'm building an instagram API app that allows editors to remove photos that are unseemly. Photos are pulled from Instagram in batches of 20 and displayed to editors. If an editor clicks a photo, it is first put on a 'blacklist' database by ID, then deleted from the main photo database.
In order to not have blacklisted photos reappear on the feed, before saving an item to the main photo database, it needs to check the Instagram ID of the photo against the blacklist. To do this, I'm using a Schema method.
The problem right now, is that I'm only getting ONE photo saved to the DB. If I take out the method check, then I get all 20.
Here's my main create controller:
exports.create = function(req, res) {
var topic = req.body.topic || 'nyc';
var path = 'https://api.instagram.com/v1/tags/' + topic + '/media/recent?client_id=' + 'XXXXXXXXXX';
request.get({url: path}, function(err, response){
if (err){
console.log('Failed to get data: ', err);
return res.status(400).json({error: 'Not allowed'});
}
else{
// ------------------------------------------------
// Make sure we have JSON
//
var body = JSON.parse(response.body);
// ------------------------------------------------
// Loop through each response
//
for (var i = 0; i < body.data.length; i++ ){
var photoData = body.data[i];
// ------------------------------------------------
// If there is no caption, skip it
//
if (!photoData.caption){
text = '';
}
else{
text = photoData.caption;
}
// ------------------------------------------------
// Create new photo object
//
var photo = new Photo({
link: photoData.link,
username: photoData.user.username,
profilePicture: photoData.user.profile_picture,
imageThumbnail: photoData.images.thumbnail.url,
imageFullsize: photoData.images.standard_resolution.url,
caption: text,
userId: photoData.user.id,
date: photoData.created_time,
_id: photoData.id
});
photo.checkBlacklist(function(err, blacklist){
if (!blacklist){
photo.save(function(err, item){
if (err){
console.log(err);
}
console.log('Saved', item);
})
}
});
// -------------------------------------------------
//
// Save
//
// -------------------------------------------------
} // END FOR LOOP
console.log('Photos saved');
return res.json(201, {msg: 'Photos updated'} );
}
});
};
And here's my Schema for photos:
'use strict';
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
var Blacklist = require('../blacklist/blacklist.model');
var PhotoSchema = new Schema({
created: {type: Date, default: Date.now()},
date: String,
link: String,
username: String,
profilePicture: String,
imageThumbnail: {type: String, unique: true},
imageFullsize: String,
caption: String,
userId: String,
_id: {type: String, unique: true}
});
PhotoSchema.methods.checkBlacklist = function(callback){
return Blacklist.findById(this._id, callback);
};
module.exports = mongoose.model('Photo', PhotoSchema);
Strangely, I'm getting console messages for all 20 saves in the create controller:
console.log('Saved', item);
But only ONE photo is actually saved. Any ideas why?
Thanks
When you have to perform the same asynchronous task for items in an array, don't use a regular for loop. Check out async.each, it fits better in your scenario, like (just the else part of your code):
var body = JSON.parse(response.body);
async.each(body.data, function (photoData, callback) {
// ------------------------------------------------
// If there is no caption, skip it
//
if (!photoData.caption){
text = '';
}
else{
text = photoData.caption;
}
// ------------------------------------------------
// Create new photo object
//
var photo = new Photo({
link: photoData.link,
username: photoData.user.username,
profilePicture: photoData.user.profile_picture,
imageThumbnail: photoData.images.thumbnail.url,
imageFullsize: photoData.images.standard_resolution.url,
caption: text,
userId: photoData.user.id,
date: photoData.created_time,
_id: photoData.id
});
photo.checkBlacklist(function(err, blacklist){
if (!blacklist){
photo.save(function(err, item){
if (err){
console.log(err);
}
console.log('Saved', item);
callback();
});
}
});
}, function (error) {
if (error) res.json(500, {error: error});
console.log('Photos saved');
return res.json(201, {msg: 'Photos updated'} );
});
Don't forget to install
npm install async
and require async:
var async = require('async');
How about solving it recursively
saveGames = (depth) => {
if (depth > 0) {
var newGame = new Game({ user: user._id });
newGame.save((err, game) => {
if (err) {
console.log(err);
return res.status(203).json({
title: 'error',
error: { message: 'Error Saving Games' }
});
}
user.games.push(game);
user.save((err, user) => {
if (err) {
console.log(err);
return res.status(203).json({
title: 'error',
error: { message: 'Error Saving Games' }
});
}
saveGames(depth - 1);
});
});
}
}
saveGames(5);
I'd need some help on returning values after saving a new entry to my db using mongoose.
This is how my controller looks:
var userModel = require('../models/users');
module.exports = {
findAll: function(req, res) {
userModel.user.findAll(function(err, users) {
return res.json(users);
});
},
findId: function(req, res) {
var id;
id = req.params.id;
userModel.user.findId(id, function(err, user) {
return res.json(user);
});
},
addUser: function(req, res) {
newUser = new userModel.user;
newUser.username = req.body.username;
newUser.password = req.body.password;
newUser.addUser(function(err, user) {
return res.json(user);
});
}
};
And here's my users.js:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var UserSchema = new Schema({
username: {
type: String,
required: true
},
password: {
type: String,
required: true
}
});
module.exports = {
findAll: UserSchema.statics.findAll = function(cb) {
return this.find(cb);
},
findId: UserSchema.statics.findId = function(id, cb) {
return this.find({
_id: id
}, cb);
},
addUser: UserSchema.methods.addUser = function(cb) {
return this.save(cb);
}
};
This all works ok, but it only returns me the newly added user with addUser. I would like to get all the entries, including the newsly added one, as a return value. Just like using "findAll". How would be able to do this?
Yes, like bernhardw said there doesn't seem to be a way to return anything but the added document with save().
I followed his advice and called findAll() inside addUser() and it all works perfect now -> I can return all my users after saving a new new one. Thanks.