I am developing an express webapp that has a friends list feature, the list is an array that is part of the user record in the database. What I am trying to do is to set up a route that adds the user from the route parameter to the logged in user's friends list array and updates the database.
My approach is to acquire the friends list document via collection.find() query (which works), modify it via javascript and update the database in a callback function.
The modifying part is what causes me problems, since the mongodb queries don't return json, but mongodb query objects. I don't know how to parse them. How can I get only the values to edit from that document?
router.get('/users/:specifiedUser/addfriend', function(req, res){
var currentUser = req.user.username;
var specifiedUser = req.params.specifiedUser;
var db = req.db;
var collection = db.get('usercollection');
var friendsList = [];
collection.find({ username : currentUser },{ friendsList : 1 }, function (err, result){
//TODO: convert result values to friendsList array, append specifiedUser to the array that is then updated in the callback
collection.update({username : currentUser },{friendsList : friendsList }, function (err) {
if (err) {
// return error if it fails
console.log(err.message);
return res.render('index', { error : err.message });
};
});
if (err) {
// return error if it fails
console.log(err.message);
return res.render('index', { error : err.message });
};
});
});
Related
I am using node and MongoDB for my project, here I need to set the filter on node script so that the data comes out from my MongoDB is filtered. But I do not understood how to use filter functionality on my script. It will be a filtered method, or I can use find method, or use loop
to filter the data in my MongoDB using node js script.
I am not exactly getting the idea.
What I want to do?
1) I had sent a set off a question from my MongoDB to the frontend.
2) Questions Data is coming from the front end and saved via using node js API. I have to save questionId, a score.
3) Next time when I have to send the data I NEED FILTER HERE so that data I have sent previously not sent again.
Id will generate automatically in MongoDB. So I have not mention id here.
This is my question schema
title: {type: String, required:true},
options: {type: Array, required:true},
result: {type: Array, required:true},
here i am storing my questionid, score values coming from frontend.
This is my question id, score save schema
child: {
quiz: {
questionId:{type:String},
score:{type:Number},
time:{type:String}
}
}
This is my node js API filter. I am trying this but I am not sure this is right or wrong. Please help me to fix this proble.m
this.childfilter = function(req, res, next) {
async.waterfall ([
function(callback) {
try {
var query = { 'child.quiz.score': 1 };
var projection = '';
childinfo.find(query,function(err,data) {
if(err) return next(err);
res.send(data);
callback(null, data)
});
}
catch(err) {
console.log(err);
return next(err);
}
},
function(callback, data) {
try {
var childq = new childquestion();
var query = { 'data.child.quiz.questionId' : childq._id };
var projection = 'id title options result';
childquestion.find(query,projection)
.skip()
.exec(function(err,data){
if (err) return next(err);
res.send(data);
});
}
catch(err) {
console.log('Error While Saving the result ' +err);
return next(err);
}
}
]);
}
im writing a query in node js, my model of schema has 3 objects( userid, tokenid, mediaid), and i want to find the token id of a certain userid and use it in another function.
my code is as below:
app.get('/registeruser/:userid', function(req, res){
var name = req.params.userid;
user.findOne({userid: name},function(err, users1){
if(!users1){
res.send('Error 404, user not found');
return res.status(404).send();
}
else{
var query = user.find({tokenid: 1});
query.where({userid: name});
query.exec(function(err, result){
if(err){
res.send('erooooooor')
}
else{
res.send('okk')
console.log(result)}
});
user is the name of my model.
i run my code and i expect it to return the tokenid but it returns this: []
with these in my database:
userid: 'hgfj1234',
tokenid: 'juiodkdn12345678',
mediaid: ['med10', 'med11']
when i write userid: 'hgfj1234' it gives me this: [] but i want the real tokenid.
if anyone can help me i really appreciate it.
thanks in advance.
You don't need to do additional request to get record from mongodb.
That's enough to use findOne with complex attributes.
Try this:
app.get('/registeruser/:userid', function(req, res) {
var query = {
userid: req.params.userid,
tokenid: {$exists: true, $not: {$size: 0}}
};
user
.findOne(query)
.exec(function(err, User) {
if(err) { // error happen,
console.error(err); // log error
return res.status(500).send({
success: false,
message: 'System error'
}); // respond with 500 status and send json response with success false and message. return will stop execution to go down
}
if(!User) { // response from database was empty or null
return res.status(404).send({
success: false,
message: 'User not found'
}); // respond with 404 status and send json response with success false and message. return will stop execution to go down
}
res.send({
success: true,
tokenid: User.tokenid
}); // and at last everything is ok, we return json response with success and tokenid in response
});
});
attributes in query variable means to request mongodb to give us document with userid defined in request and that has tokenid that is defined and not is empty string (not size 0).
if You still did not getting desired result so check database for existence of necessary document.
If I understand your query right, you will reduce all find() calls to the tokenid with value 1. You will receive only any result, if the user has the token "1".
I suspect you wanted to code a projection, that is the second parameter on find():
var query = user.find({"userid": name});
query.select({"tokenid": 1})
.exec(function(err, result){
if(err){
res.send('erooooooor')
}
else{
res.send('okk')
console.log(result)}
});
postRegistrationHandler: function (account, req, res, next) {
console.log('postRegistrationHandler activated');
account.getCustomData(function(err, data) {
if (err) {
console.log(err.toString, "error string");
return next(err);
} else {
data.mongo_id = userCreationCtrl(account);
data.save();
next();
}
});
},
This function almost works properly, but the line:
data.save();
runs before the previous line finishes which means that the data I want to save isn't present at the appropriate time.
data.mongo_id = userCreationCtrl(account);
This line calls a function that creates a mongoDB document with information in the account object and then returns the _id (which is what I am trying to save.
I thought maybe using a .then() would help but that seems to be unavailable here for some reason. If anyone sees something I'm missing, that would be quite helpful. Thank you!
Here is the userCreationCtrl file as requested:
var UserSchema = require('./../models/UserModel.js');
var createNewUser = function (account, res, next){
// We will return mongoId after it is created by submitting a newUser
var mongoId = "";
// Save StormpathID (last 22 characters of account.href property)
var newStormpathId = account.href.slice(account.href.length - 22);
console.log('stormpath ID:', newStormpathId, 'just registered!');
console.log(account);
// Create new user from model by recycling info from the Stormpath registration form and include the stormpathId as well.
var newUser = new UserSchema({
stormpathId: newStormpathId,
firstName: account.givenName,
lastName: account.surname,
email: account.email,
street: account.street,
city: account.city,
zip: account.zip
});
// This saves the user we just created in MongoDB
newUser.save(function(err, result){
console.log(result);
if (err) {
console.error(err);
}
else {
console.log("User created in MongoDB, attempting to return mongoDB _id to stormpath customData");
// Keep track of the new user's mongo _id so we can return it to the previous function and save it as Stormpath custom data.
mongoId = result._id;
console.log(mongoId, "mongoid");
return result._id;
}
});
};
module.exports = createNewUser;
You have userCreationCtrl expecting 3 arguments, account, res, and next. next is the callback that should be called after the user is created so instead of return result._id you should call next like so:
// inside of createNewUser()
newUser.save(function(err, result){
console.log(result);
if (err) {
console.error(err);
}
else {
console.log("User created in MongoDB, attempting to return mongoDB _id to stormpath customData");
// Keep track of the new user's mongo _id so we can return it to the previous function and save it as Stormpath custom data.
mongoId = result._id;
console.log(mongoId, "mongoid");
// IMPORTANT change to make it all work...
// get rid of return result._id because its not doing anything
// pass the value to your callback function instead of returning the value
next(null, result._id);
}
});
then calling code in postRegistrationHandler should look like this:
account.getCustomData(function(err, data) {
if (err) {
console.log(err.toString, "error string");
return next(err);
} else {
// pass in a callback as the 3rd parameter that will be called by newUser.save() when its finished
userCreationCtrl(account, null, function(err, resultId) {
data.save();
next();
});
}
});
I've got this error when trying to POST
> process.nextTick(function() { throw err; });
> ^
>
> TypeError: first argument must be a string or Buffer
> at ServerResponse.OutgoingMessage.end (_http_outgoing.js:524:11)
Errors shows that something's wrong with utils and cursor both from mongodb module, but what are they?
Everything works nice on GET but brakes on POST (postman and passing as text {"name":"Computer","price":2500}) - i cannot trace which module or instance is braking the code.
This is my conn with db:
// Our primary interface for the MongoDB instance
var MongoClient = require('mongodb').MongoClient;
// Used in order verify correct return values
var assert = require('assert');
var connect = function (databaseName, callBack) {
var url = 'mongodb://localhost:27017/' + databaseName;
MongoClient.connect(url,
function (error, database) {
assert.equal(null, error);
console.log("Succesfully connected to MongoDB instance!");
callBack(database);
});
};
exports.find = function (databaseName, collectionName, query, callback) {
connect(databaseName, function (database) {
var collection = database.collection(collectionName);
collection.find(query).toArray(
// Callback method
function (err, documents) {
// Make sure nothing went wrong
assert.equal(err, null);
// Print all the documents which we found, if any
console.log("MongoDB returned the following documents:");
console.dir(documents)
callback(err, documents);
// Close the database connection to free resources
database.close();
})
})
};
exports.insert = function (databaseName, collectionName, object, callback) {
connect(databaseName, function (database) {
var collection = database.collection(collectionName);
collection.insert(document, {w: 1}, function (err, documents) {
console.log("Added a new document");
console.log(documents[0]);
callback(err, documents[0]);
});
})
};
exports.remove = function (databaseName, collectionName, object, callback) {
connect(databaseName, function (database) {
var collection = database.collection(collectionName);
collection.remove(object, function (err, result) {
callback(err, result);
database.close();
});
})
};
The issue is actually pretty straightforward, so I'm surprised that you're not getting a better error message.
In your code:
collection.insert(document, {w: 1}, function (err, documents) {
console.log("Added a new document");
console.log(documents[0]); // I expect this to log undefined
callback(err, documents[0]);
});
The second argument passed into the collection.insert callback is actually a results object, not the documents that were inserted. So, documents[0] ends up being undefined because it's not an array of documents. Thus, when you trying to send undefined as a response, it's failing.
If you intention is to pass the newly created documents, you're going to have to use the result object to get the _id and attach it to the document you inserted.
As a side note, I would consider keeping a connection open to your database rather than creating a new connection every time you want to talk with Mongo.
I can connect to my database from node.js using the MongoClient. I amb able to write, update and remove docs from a collection. But I am not able to retrieve data from it. This is my code:
var mongoClient=require('mongodb').MongoClient;
var mongoDbObj;
mongoClient.connect('mongodb://127.0.0.1:27017/trendoa', function(err, db){
if(err){
console.log(err);
}else{
global.db = db;
};
var col = global.db.collection('twitter_accounts_mon');
// create
var doc1 = {'hola':'sushi'};
col.insert(doc1, function(err, result) {
callback(err);
});
// update
col.update({hola:'jordi'}, {$set:{hola:'joan'}}, {w:1}, function(err, result) {});
// delete
col.remove({hola:'jordi'}, function(err, result) {
callback(err);
});
// read
col.find().toArray(function(err, docs) {
console.log(docs);
});
What I'm trying to do in the last lines of code is to get all the documents using find() but it doesn't return any results.
Through the mongo shell, using this command I get data on screen:
db.twitter_accounts_mon.find()
I don't know what I'm doing wrong. Thanks!
the nodejs callbacks must nest, ie only search the collection once the db is open
mongoClient.connect('mongodb://127.0.0.1:27017/trendoa', function(err, db){
var col = db.collection('twitter_accounts_mon');
coll.find({}, function(err, cursor) {
cursor.toArray(function(err, data) {
// process the data array
}
}
}
According to the MongoDB documentation on the Node.js driver, the find method does not execute the actual query, it builds an instance of a cursor that you then use to retrieve data. thus, you need to handle the result of the query.
var entireCollectionArray = col.find().toArray(function(err, items) {});
entireCollectionArray.forEach(function (element) {
console.log(element);
});