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.
Related
When i Try to push key:value pair with the following code, it inserts data as object instead of key value pair. Following is the code im using to insert data into MongoDb
MongoClient.connect(url, function (err, db) {
if (err) throw err;
var dbo = db.db("Test");
var myquery = { userId: "test#gmail.com" };
// var newvalues = { $set: { name: "Mickey", address: "Canyon 123" } };
var newvalues = {
$push: { questionAnsId: { $each: [{ wk: 5 }] } }
}
dbo.collection("Forms").updateOne(myquery, newvalues, function (err, res) {
if (err) throw err;
console.log("1 document updated");
db.close();
});
});
Upon inserting data, this is what im getting
enter image description here
instead of saving data in
questionAnsId: {Object}
i want to save it as
questionAnsId:{key:value, key:value}
Any Idea how to solve this ?
I am new to node and mongo db. I have a list of users with delete link in each row.I am trying to delete a user with its _id. However its not working.
Here is my router code.
router.get('/delete/:id', function (req,res) {
const ObjectId = require('mongodb').ObjectID;
var id = req.params.id;
console.log(id);
db.collection('users').deleteOne({ _id: ObjectId(req.params.id) }, function(err, res) {
if (err) {
throw err;
} else {
return res.redirect('/');
}
});
});
Here is my view, on clicking this link I am getting the _id in my url as this : http://localhost:3000/delete/4428439e14e3343ba4ac31c1
<td>Delete</td>
console.log(id) gives me 4428439e14e3343ba4ac31c1
But it throws me the below error
Error: Argument passed in must be a single String of 12 bytes or a string of 24 hex characters
at new ObjectID
Try this, you don't need to create ObjectID if the string is a valid ObjectID
For prevention, you can use a function like below to test if valid ObjectID is passed or not
function validateObjectId (id) {
if (ObjectId.isValid(id)) {
const obj = new ObjectId(id);
if (obj == id) {
return true;
}
}
return false;
},
if(!validateObjectId(req.params.id))
return res.send({'error':'Invalid ObjectID Passed',id:req.params.id});
db.collection('users').deleteOne({ _id: ObjectId(req.params.id) }, function(err, res)
{
if (err) {
throw err;
} else {
return res.redirect('/');
}
});
Also remove extra space from here
<td>Delete</td>
You need to create a instance of ObjectId using new. Currently, you are passing the ObjectId directly so you are getting that error.
db.collection('users').deleteOne({_id: new ObjectId(req.params.id)}, function(err, res) {
if (err) {
throw err;
} else {
return res.redirect('/');
}
});
you can use findByIdAndRemove
router.get('/delete/:id', function (req,res) {
var id = req.params.id;
db.collection('users').findByIdAndRemove( id , function(err, res) {
if (err) {
throw err;
} else {
return res.redirect('/');
}
});
});
Maybe you can try this code below:
router.get("/delete/:id", function(req, res) {
const ObjectId = require("mongodb").ObjectId;
var { id } = req.params;
console.log(id);
db.collection("users").findOneAndDelete({ _id: ObjectId(id) }, function(
error,
response
) {
if (error) {
throw err;
} else {
return res.redirect("/");
}
});
});
Updated:
Try looking at your code. There's confusing code, you use 2 times res. One is res from express and the other isres when it succeeds in removing at mongodb.
So, the res.redirect ('/') that you use in your mongodb function is res from mongodb, notres from express.
Try replacing {err, res} with {error, response}.
I hope it can help you.
I received an error when I manually deleted an index from elasticsearch. This happen after manually deleted and I use User.search function in the route. This is the error:
Error: [search_phase_execution_exception] all shards failed
The reason why I manually deleted the index is because mongoosastic has a known issue where, whenever I delete documents from mongodb, elasticsearch still has the documents with it.
Here's the code
models/user.js
var mongoose = require('mongoose');
var mongoosastic = require('mongoosastic');
var Schema = mongoose.Schema;
var UserSchema = new Schema({
private: false,
twitter: String,
tokens: Array,
username: String,
displayName: String,
picture: String,
});
UserSchema.plugin(mongoosastic, {
hosts: [
'localhost:9200'
]});
module.exports = mongoose.model('User', UserSchema);
router.js
User.createMapping(function(err, mapping) {
if (err) {
console.log('error creating mapping (you can safely ignore this)');
console.log(err);
} else {
console.log('mapping created!');
console.log(mapping);
}
});
var stream = User.synchronize();
var count = 0;
stream.on('data', function(err, doc){
count++;
});
stream.on('close', function(){
console.log('indexed ' + count + ' documents!');
});
stream.on('error', function(err){
console.log(err);
});
/* The result for searching for User's */
router.get('/search', function(req, res, next) {
console.log(req.query.q);
if (req.query.q) {
User.search({
query_string:
{ query: req.query.q }
}, function(err, results) {
if (err) return next(err);
console.log(results);
var data = results.hits.hits.map(function(hit) {
return hit;
});
console.log(data);
return res.render('main/search_results', { data: data });
});
}
});
I am trying to set up my nodejs app with a CRUD for mongodb sub-docs using Mongoose but can't figure out how to access the nested object's _id. I can only get the parent ObjectId. I can perform a .push on a new child object but can't perform a simple get, put or delete on an existing child object.
Here is my schema:
//new user model
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var ObjectId = Schema.ObjectId;
// Task schema
var taskSchema = mongoose.Schema({
clientEasyTask : { type: String },
clientHardTask : { type: String },
clientStupidTask : { type: String }
});
var userSchema = new mongoose.Schema({
email: { type: String, unique: true, lowercase: true },
password: String,
task : [taskSchema]
});
module.exports = mongoose.model('Task', taskSchema);
module.exports = mongoose.model('User', userSchema);
Here is my routes:
'use strict';
var isAuthenticated = require('./middleware/auth').isAuthenticated,
isUnauthenticated = require('./middleware/auth').isUnauthenticated;
var User = require('./models/user');
var Task = require('./models/user');
// Create user.task
module.exports = function (app, passport) {
app.post('/api/tasks', isAuthenticated, function (req, res) {
var userEmail = req.body.email;
var easyTask = req.body.easyTask;
User.findOne({ 'email' : userEmail }, function(err, user) {
console.log('found user and defining status and data');
var status;
var data;
if (err) {
status = 'error';
data = 'unknown error occurred';
}
if (user === null) {
status = 'error';
data = 'user not found';
} else {
status = 'ok';
data = user;
}
user.task.push({
clientEasyTask: easyTask
});
user.save();
res.json({
response: {
'status': status
}
});
});
});
// Get one user.task
app.get('/api/tasks/:id', function (req, res) {
return Task.findById(req.params.id, function(err, task) {
if(!task) {
res.statusCode = 404;
return res.send({ error: 'Not found' });
}
if(!err) {
return res.send({ status: 'OK', task:task });
} else {
res.statusCode = 500;
console.log('Internal error(%d): %s', res.statusCode, err.message);
return res.send({ error: 'Server error' });
}
});
});
};
I am using Postman to test everything so there is no fronted code. When I pass the _id of the task (nested in the user) I receive null when I call Get on '/api/tasks/:id'. How can I can get only the specific task?
The mongoose documentation states that you can use parent.children.id(id); but I couldn't get it to work.
The task field of User contains the tasks as embedded subdocs, not references to another collection, so you can't query tasks independent of users (like you're trying to do).
To query for the embedded task subdoc, you can use a query like this:
User.findOne({'task._id': req.params.id})
.select('task.$') // Just include the matching task element
.exec(function(err, user) {
if(!user) {
res.statusCode = 404;
return res.send({ error: 'Not found' });
}
if(!err) {
// The matching task will always be in the first element of the task array
return res.send({ status: 'OK', task: user.task[0] });
} else {
res.statusCode = 500;
console.log('Internal error(%d): %s', res.statusCode, err.message);
return res.send({ error: 'Server error' });
}
}
);
To make this efficient, you'd want to add an index on {'task._id': 1}.
I am easily and successfully passing a single model into a view in one of my express routes like this:
exports.locations = function(req, res){
Location.find(function(err, results) {
res.render('locations', { title: 'Locations', locations: results });
});
};
I have another route where I need to pass 2 result sets into the view, how do I do that? I have tried doing this, but it doesn't seem to be working:
exports.locationdetail = function(req, res) {
var packages = Package.find();
Location.findById(req.params.id, function(err, result) {
res.render('location-detail', { title: 'Location Details', location: result, packages: packages });
});
};
Edit 1
The error I am getting is:
Cannot read property 'name' of undefined
My model looks like this:
var mongoose = require('mongoose')
,Schema = mongoose.Schema;
var PackageSchema = new mongoose.Schema({
name: String,
prev_package: String,
featured: Boolean,
services: Array
});
module.exports = mongoose.model('Package', PackageSchema);
And I am using this model in another view, and everything is working like a champ.
var mongoOp = require("./models/mongo");
var async = require('async');
router.get("/",function(req,res){
var locals = {};
var userId = req.params.userId;
async.parallel([
//Load user data using Mangoose Model
function(callback) {
mongoOp.User.find({},function(err,user){
if (err) return callback(err);
locals.user = user;
callback();
});
},
//Load posts data using Mangoose Model
function(callback) {
mongoOp.Post.find({},function(err,posts){
if (err) return callback(err);
locals.posts = posts;
callback();
});
}
], function(err) { //This function gets called after the two tasks have called their "task callbacks"
if (err) return next(err); //If an error occurred, we let express handle it by calling the `next` function
//Here `locals` will be an object with `user` and `posts` keys
//Example: `locals = {user: ..., posts: [...]}`
res.render('index.ejs', {quotes: locals.user,userdata: locals.posts})
});
});
So, it looks like this was another asynchronous "gotcha". Putting this into a nested callback did the trick:
exports.locationdetail = function(req, res) {
Location.findById(req.params.id, function(err, result) {
Package.find(function (err, results) {
res.render('location-detail', { title: 'Location Details', location: result, packages: results });
});
});
};