Hello (I hope my English is not to bad) !
I'm actually trying to start a basic database with MongoDB atlas (the online alternative), but I cannot pass the first step : connecting! I've got always the same error :
throw err;
^
Error: Missing delimiting slash between hosts and options
at parseConnectionString (C:\Users\Etudiant1\Documents\Cours\ProjetPerso\Bot\node_modules\mongodb\lib\url_parser.js:164:11)
at parseHandler (C:\Users\Etudiant1\Documents\Cours\ProjetPerso\Bot\node_modules\mongodb\lib\url_parser.js:129:14)
at module.exports (C:\Users\Etudiant1\Documents\Cours\ProjetPerso\Bot\node_modules\mongodb\lib\url_parser.js:25:12)
at deprecated (internal/util.js:47:15)
at connect (C:\Users\Etudiant1\Documents\Cours\ProjetPerso\Bot\node_modules\mongodb\lib\operations\mongo_client_ops.js:180:3)
at connectOp (C:\Users\Etudiant1\Documents\Cours\ProjetPerso\Bot\node_modules\mongodb\lib\operations\mongo_client_ops.js:284:3)
at executeOperation (C:\Users\Etudiant1\Documents\Cours\ProjetPerso\Bot\node_modules\mongodb\lib\utils.js:420:24)
at MongoClient.connect (C:\Users\Etudiant1\Documents\Cours\ProjetPerso\Bot\node_modules\mongodb\lib\mongo_client.js:168:10)
at Function.MongoClient.connect (C:\Users\Etudiant1\Documents\Cours\ProjetPerso\Bot\node_modules\mongodb\lib\mongo_client.js:372:22)
at Object. (C:\Users\Etudiant1\Documents\Cours\ProjetPerso\Bot\testMongo.js:4:13)
I've already seen some similar error on stack overflow but I didn't find a solution for my problem. My code is as following :
var MongoClient = require('mongodb').MongoClient;
var uri = "mongodb://Admin:<PASSWORD>#cluster0-shard-00-00-xm3ps.mongodb.net:27017,cluster0-shard-00-01-xm3ps.mongodb.net:27017,cluster0-shard-00-02-xm3ps.mongodb.net:27017/test?ssl=true&replicaSet=Cluster0-shard-0&authSource=admin&retryWrites=true";
MongoClient.connect(uri, function(err, db) {
// Paste the following examples here
if(err){
throw err;
} else {
console.log("Connected");
}
db.close();
});
Thanks already !
Hey Laura welcome to StackOverflow! I've included code and explanation below:
MongoClient.connect(uri, { useNewUrlParser: true }, function(err, db) {
if (err) {
console.log("error connecting");
} else {
console.log("success connecting");
//do something like insert,update,etc.
db.close();
}
});
It looks like you are missing useNewUrlParser: true
You will want to use db.close() method after you've performed an operation
For security purpose, you may not want to write out the URL explicitly, rather store as an environment variable and reference instead.
var uri = process.env.mongoURI instead of var uri = mongodb://...
Related
I am new to Nodejs and Express and want to search some results from mongoDB and show it on client browser, i can find the values from the mongoDB query but not able to send it to client js file,
It says doc is not defined, any help will be appreciated.
***app.js(Server)***
var bodyParser = require("body-parser");
var express = require("express");
var app = express();
var port = "8001";
var mongo= require('mongodb');
var mongoClient=mongo.MongoClient;
app.use(bodyParser.json());
app.use(express.static('public'));
app.get('/home', function(req, res) {
res.sendFile(__dirname + "/public/views/index.html");
});
app.listen(port, function() {
console.log("Server running at:" + port);
})
app.post("/response", function(req, res) {
var t = req.body;
mongoClient.connect("mongodb://localhost:27017/query", function(err,db){
cursor =db.collection('response').find({"name1":t.text},{"name2":1, "_id":0});
cursor.each(function(err, doc) {
if (doc != null) {
console.log(doc);
}
});
})
res.send(doc);
});
***index.js(Client Side)***
$.ajax({
url: '/response',
type:"POST",
contentType:"application/json; charset=utf-8",
complete: function(data) {
console.log(data.responseText);
alert(data.responseText);
}
});
doc is a variable local to your closure and therefore not available when you call res.send(doc).
In addition to that, you are iterating over all of your documents. You need to choose which one to return.
I recommend something like this:
cursor = db.collection('response').find({"name1":t.text},{"name2":1, "_id":0});
cursor.each(function(err, doc) {
if (doc != null) {
console.log(doc);
return res.json(doc); // return the first document found
}
});
Also note:
you should sanitize your data before passing it into the query
you shouldn't connect to the database on each request, instead set up mongo in the application context
you should check err to see if mongo returned an error before trying to iterate the cursor
EDIT:
To be more specific, the whole block should look like this:
app.post("/response", function (req, res) {
var t = req.body;
mongoClient.connect("mongodb://localhost:27017/query", function (err, db) {
if (err) {
return res.json(err);
}
db.collection('tweets').findOne({"name1": t.text}, {"name2": 1, "_id": 0}, function (err, doc) {
if (doc != null) {
console.log(doc);
return res.json(doc);
}
return res.sendStatus(404);
});
});
});
A few things:
cursor.each() has been deprecated in favour of cursor.forEach() assuming you're running a recent version of mongo
Your first line in a callback should be something like if (err) { console.error(err) } - at this point you'd probably see that your query is invalid:
Your query should probably look like .find({'name1': t.text, 'name2': 1, '_id': 0})
If you are referencing an auto-generated mongo ObjectID as _id, you have to use '_id': new mongo.ObjectID(<whatever string holds the _id>) in order for it to work. If you didn't specify an _id on creation, the automatically generated ObjectID will require this.
The mongo docs are great, highly recommend leafing through them for examples and which bits take which arguments and the options for all of them.
Consider using promises instead of callbacks to help tidy up. It's really easy with mongo - you just don't specify a callback function, and instead tack a .then(document => { ... }) on the end, and a single .catch(err => {console.error(err)}) will catch errors at the db, collection and cursor levels.
With jQuery, consider using .done(result => {...}) and .fail(err => { ... }) (aka promises) instead of complete for your ajax calls, and whatever you do, don't forget to attach an error handler. (I'm not even sure 'complete' is the right property, might depend on which jQuery you're using)
If you're doing an AJAX POST you should probably attach some data (and a dataType)to it. Otherwise you'll still get no records because req.body will be undefined or empty.
In the case of an error, you should be responding with res.status(500); res.end() at a minimum so you can tell when something has gone wrong on the server end.
To help along, console.log(req.body) right at the top of your function so you know what data is arriving.
Finally, if you intend on responding with JSON - use res.json(doc) instead of res.send(doc)
I seem to be having issues performing HTTP Put requests inside an array in AngularJS and ExpressJS. The issue is, when I call the HTTP Put the first time, everything works correctly. However, when I try to call a second time, it doesn't work. The following is my attempt:
When I click a button, I call perform the following HTTP Put Request:
$scope.currentUser.eventsAttending.push(event.eventName);
$http.put('/api/users/' + $scope.currentUser._id, $scope.currentUser)
.success(function(data){
console.log("Success. User " + $scope.currentUser.name);
});
Here is my User schema/model in User.model.js:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var User = require('./user.model');
var UserSchema = new Schema({
name: String,
...
eventsAttending: [{ type: String, ref: 'Event'}]
});
I route the HTTP Put Request as so in index.js:
router.put('/:id', controller.update);
And here is my actual HTTP Put function called controller.update in User.controller.js:
// Updates an existing event in the DB.
exports.update = function(req, res) {
if(req.body._id) { delete req.body._id; }
User.findById(req.params.id, function (err, user) {
if (err) { return handleError(err); }
if(!user) { return res.send(404); }
var updated = _.merge(user, req.body);
updated.markModified('eventsAttending');
updated.save(function (err) {
if (err) { return handleError(err);}
return res.json(200, user);
});
});
};
...
function handleError(res, err) {
console.log("Error: ", err);
return res.send(500, err);
}
On the second time where I try to call the HTTP Put function (exports.update above), I always get an error in Mongoose that says:
TypeError: Object VersionError: No matching document found. has no method 'send'
at handleError (/Users/schan/test/go-v2/server/api/user/user.controller.js:131:14)
at Promise.<anonymous> (/Users/schan/test/go-v2/server/api/user/user.controller.js:43:25)
The error is basically where I call the if(err) return { handleError(err); } in the HTTP Put function and when I print out the error, I get Error undefined. I'm honestly unsure on how to debug this or what I may be doing wrong. Can anyone point me in the right direction? If so that would be great! Thanks.
You're not passing res to handleError(). Change instances of handleError(err); to handleError(res, err);
Let's imagine we have Node.JS app which is connecting to the Mongos process. But suddenly Mongos failed. How our app could now about it?
var db = null;
mongo.MongoClient.connect('mongodb://127.0.0.1:27017/test', function(err, mydb) {
if(err) throw err;
db = mydb
});
..... on response we have .....
db.collection('test_collection', function(err, collection){
collection.find({}).toArray(function(err, documents){
// doing some work here
// but if Mongos failed, we are blocked on this stage
});
});
Would you not want to do the same thing that you're doing at connect, but within the function?
i.e.
...
collection.find({}).toArray(function(err, documents) {
if(err) {
throw err; //or do something equivalent. It doesn't really matter if the connection has failed, as it will still throw an error.
} else {
///continue processing
}
....
Alternatively, if you use a 3rd party mongo manager, such as mongoose, you can do something like this globally:
mongoose.connect('mongodb://' + config.mongo.host + '/' + config.mongo.db);
var db = mongo.connection;
db.on('error', console.error.bind(console, 'connection error: '));
I've built a series of database queries in my express app that reside in a /models/index.js file which I can access from app.js via var express = require('express');. I am trying to populate req.session.user with a userid that is returned by a findByEmail(); function in /models/index.js.
The findByEmail(); function works fine, however I can't figure out how to store its return value in req.session. I've tried including req.session.id = result.rows[0].id; in the 'findByEmail();function, but this returns areq is not defined` error.
Am I overlooking a simple require statement in my /models/index.js file or is there another trick to accessing req.session in a module?
I've included the relevant code from /models.index.js below:
/models.index.js:
var pg = require('pg');
function findByEmail(email){
pg.connect(function(err, client, done) {
if(err) {
console.log('pg.connect error');
throw err;
}
client.query('BEGIN', function(err) {
if(err) {
console.log('client.query BEGIN error');
return rollback(client, done);
}
process.nextTick(function() {
var text = "SELECT * FROM users WHERE email = $1";
client.query(text, [email], function(err, result) {
if(err) {
console.log(err);
return rollback(client, done);
}
console.log(result);
console.log(result.rows);
console.log('id: ', result.rows[0].id);
req.session.id = result.rows[0].id;
done();
});
});
});
});
}
module.exports.pg = pg;
exports.findByEmail = findByEmail;
As far as /models/index.js knows, req is not defined, same thing with rollback. A module is a closure and you don't have access to variables defined outside of it.
If you want to do that you must pass them as parameters but it's not very good design, as #gustavohenke said: Separation of concerns.
You might want to have a callback and call it with success/error and set the session id there so you don't have to pass in into the module:
function findByEmail(email,callback){
pg.connect(function(err, client, done) {
if(err) {
console.log('pg.connect error');
throw err;
}
// Do all the async work and when you are done ...
// An error is usually passed as the first parameter of the callback
callback(err,result)
});
}
exports.findByEmail = findByEmail;
You would then call it like this:
var models = require('./models');
models.findByEmail('thedude#lebowski.com',function(err,results) {
// set session id here where you probably have access to the req object...
})
I am trying to connect to my mongodb database, but it doesn't work : it doesn't run the callback, and no error is thrown :
var config = require('./config');
var mongoose = require('mongoose');
var schemas = require('./app/schemas');
var model = require('./app/model');
mongoose.connect(config.db_connection, function (err) {
if (err) {
throw err;
}
});
var ModModel = mongoose.model('mods', schemas.modScheme);
var query = ModModel.find();
query.exec('find', function (err, mods) {
if (err) {
throw err;
}
console.log('Retriveing mods...');
console.log(mods);
});
EDIT : This new code don't work
Here is the whole code : https://github.com/CraftYourModCorporation/RedstoneHub
(May not be complete, route getmods)
Could someone link a project that uses mongoose please ?
And output :
Important: use 'process.env.PORT' as the port and 'process.env.IP' as the host in your scripts!
debugger listening on port 15400
Process terminated
Thanks all of you, The problem was the connection string : instead of connecting using mongodb://user:pass#host/db, i had to use options. More details here : http://mongoosejs.com/docs/connections.html