Why do the Node.js mongodb driver methods not invoke callbacks - javascript

In the example below, I expect to see two lines from the console.log statements in the terminal but I only get one since the second callback is never fired. I'm using mongodb (2.4.8_1) and Node.js (0.10.22) from MacPorts with the official Node.js mongodb driver (1.3.20) from NPM (1.3.15). How can this happen?
var mongodb = require('mongodb');
mongodb.MongoClient.connect('mongodb://localhost:27017/test', function (err, db) {
var query = { _id: new mongodb.ObjectID };
console.log('connect!');
db.collection('test').findOne(query, function (err, doc) {
console.log('findOne!');
});
});

Every time you run new mongodb.ObjectID it creates a new ID value - which you then instantly search for without inserting a document with. So how can it find a document, and hence show the second log line?

Related

KNEX Undefined binding(s) detected when compiling SELECT query

var knex = require('knex')(config);
var bookshelf = require('bookshelf')(knex);
var SKU = bookshelf.Model.extend({
tableName: 'skus',
});
SKU.where('id', undefined).fetch().then(function (skus) {
if (skus) console.log(skus.toJSON());
}).catch(function (err) {
console.error(err);
});
It throws
Undefined binding(s) detected when compiling SELECT query.
It is working fine with 0.11.5, it stopped working with 0.11.6 onwards. I am pointing to 0.13.0 right now.
useNullAsDefault: true
works fine with insert queries but not select queries. Is there any flag i should pass to resolve this error?
.where('id', undefined) does not mean anything in SQL. You cannot be querying something that is not there.
Maybe you wanted to query where id IS NULL? With knex it can be done like this: .whereNull('id')
With earlier knex versions it would have been just ignored, but starting from 0.12.x.
So to have equivalent functionality with newer (and actually it is compatible with older < 0.12 versions too) knex versions you should do:
SKU.fetch().then(function (skus) {
if (skus) console.log(skus.toJSON());
}).catch(function (err) {
console.error(err);
});
Unless bookshelf is adding some extra magic there...
The useNullAsDefault: true option Is used only for when inserting multiple rows in one insert. It does not make sense to use it unless you are using sqlite (check last example of http://knexjs.org/#Builder-insert).
parameter mismatch in payload
the parameter which sql query is expecting and the parameter you sending in requestbody is not matching.
in my case sql was expecting parameter "gradeId" but in requestBody i was sending "postId"

MongoError: cursor killed or timed out - Meteor timeout settings ineffective

My Meteor 1.2.1 program threw MongoError: cursor killed or timed out in a find().forEach() loop, so i found this page that says this code prevents that:
var myCursor = db.users.find().noCursorTimeout()
However, the driver docs and my Meteor say that method doesn't exist: Object [object Object] has no method 'noCursorTimeout'
Mongo autoReconnect is enabled by default and didn't help, nor did the Meteor forum, or even .find({}, {timeout:false}) according to this comment.
2016-07-20 11:21:37 Update started
2016-07-20 11:37:21 Exception while invoking method 'updateCollections' MongoError: cursor killed or timed out
Maybe Meteor got confused by the failed SOAP call at 2016-07-20 09:34:57?
"error": {
"errno": "ETIMEDOUT",
"syscall": "connect",
"code": "ETIMEDOUT"
},
Assuming maxTimeMS would help in this case you can access it by working with rawCollection object instead of the Meteor collection itself.
It's quite simple:
var rawCollection = Meteor.users.rawCollection();
var cursor = rawCollection.find({}).maxTimeMS(5000);
var myData = fetchCursor(cursor);
Where fetchCursor is a simple fiber-aware helper function that can be implemented like this:
var fetchCursor = Meteor.wrapAsync(function fetchCursor (cursor, cb) {
cursor.toArray(cb);
});
Though, I am not sure if this method is exactly what you're looking for.
Edit
If you don't need the entire array of documents but you want to process each one of them independently it may be better to use each instead of toArray, e.g.
var fetchCursor = Meteor.wrapAsync(function fetchCursor (cursor, cb) {
cursor.each(function (err, doc) {
if (err) return cb(err);
if (!doc) return cb(null, { done: true }); // no more documents
// do something with the document ...
});
});

Simple MongoDB query find item age > 10 learnyoumongo find function

I'm going through learnyoumongo and I'm stuck on part 3. Basically a test database is included in the challenge, it is full of parrots, and the goal is to select the parrots whose age is greater than the input. I'm getting a weird error and google is full of mongo 2.x solutions to not exactly the same problem and I'm using mongo 3.0
This is the javascript code:
var mongo = require('mongodb').MongoClient;
var parsedInput = parseInt(process.argv[2]);
var results;
mongo.connect('mongodb://localhost:27017/learnyoumongo', function(err, db){
results = db.collection('parrots').find({ age: { $gt: parsedInput } } ).toArray(function(err, doc) //find if a value exists
{
if(doc) //if it does
{
console.log(doc);
}
else{
console.log(err);
}
});
//console.log(results);
db.close();
});
This is the weird error message:
PS C:\git\learnyoumongo> node .\test.js { [MongoError: server localhost:27017 sockets closed]
name: 'MongoError',
message: 'server localhost:27017 sockets closed' }
I tried restarting mongo, but I'm still not able to pull any of the 'parrots' data out. Even with just find({})
The problem was two pronged - The main issue was I was expecting to be able to run the query with node test.js, and see the results from the parrots collection. But learnyoumongo has atomic tests, meaning they clear the database entirely before and after, so the only way to test was learnyoumongo test.js, and I kept getting an empty result set running the node command.
The other issue was with db.close(), you can't just call db.open and then db.close, because open is async and it would close right after opening, hence the sockets closed error. So you put db.close in the toArray function, or in any other callback of db.open

Node.js and mongodb access mongodb

I'm trying to set up mongodb on Windows 8 using node.js, Does anyone know why im getting this error. C:\users\phill\node_modules\mongodb\lib\mongodb\mongo_client.js:359 it also says at collection = db collection,,, can't call method 'collection' of null. I'm having a hard time setting it up. My goal is to be able to add to mongo db, and see that I add or pull up what I added, but adding something is good enough for me for now. I'm trying every thing I can find, even straight from the website, I tried everything I see on here as well. Think it maybe it's the way I have things set up. My node.js is saved in my c: drive there is a file that says, program files(86x) in there I have node_modules, npm and such. The path ends up being, computer > windows (C:) > program files(86x) > nodejs. My Mongodb is saved right on my C: drive the path end up being windows (C:) > mongodb-win32-x86_64-2008plus-2.4.8. In my C: I also created a file data and in it created another db. I have been told i should just use mongoose, I'm just learning so i open to any advice, links or anything that will help. I have one last question as well, i learned php and then found out about sql injections and stuff like that, i am not seeing anything about security at all, should i expect the same as well. For this i get text not defined, but i have been getting errors with everthing i have done, best i did was get stuck on a right concern screen.
var MongoClient = require('mongodb').MongoClient;
MongoClient.connect("mongodb://localhost:27017/integration_test", function(err, db) {
test.equal(null, err);
test.ok(db != null);
db.collection("replicaset_mongo_client_collection").update({a:1},
{b:1}, {upsert:true}, function(err, result) {
test.equal(null, err);
test.equal(1, result);
db.close();
test.done();
});
});
Tried this as well and getting a error,C:\users\phill\node_modules\mongodb\lib\mongodb\mongo_client.js:359.... at collection = db collection,,, can't call method 'collection' of null. im calling it in command prompt node filename.js I'm saving it where my node.js file is, I have pulled up files before and created a server.
var Db = require('mongodb').Db,
MongoClient = require('mongodb').MongoClient,
Server = require('mongodb').Server,
ReplSetServers = require('mongodb').ReplSetServers,
ObjectID = require('mongodb').ObjectID,
Binary = require('mongodb').Binary,
GridStore = require('mongodb').GridStore,
Grid = require('mongodb').Grid,
Code = require('mongodb').Code,
BSON = require('mongodb').pure().BSON,
assert = require('assert');
var db = new Db('test', new Server('localhost', 27017));
// Fetch a collection to insert document into
db.open(function(err, db) {
var collection = db.collection("simple_document_insert_collection_no_safe");
// Insert a single document
collection.insert({hello:'world_no_safe'});
// Wait for a second before finishing up, to ensure we have written the item to disk
setTimeout(function() {
// Fetch the document
collection.findOne({hello:'world_no_safe'}, function(err, item) {
assert.equal(null, err);
assert.equal('world_no_safe', item.hello);
db.close();
})
}, 100);
});
In your first code example, you said:
For this i get text not defined
I assume you meant "test not defined?" Your script only requires the mongodb library, and I don't believe test is a core nodejs function, so that would explain the error.
To reference the driver documentation for db.collection(), an assert library is used, but also properly imported (as you did in your second example).
Within your callback to db.open(), you don't check if an error occurred. That might shed some light on why db is null in that function.
Regarding your question about the equivalent of SQL injection with MongoDB, the main areas of concern are places where you might pass untrusted input into evaluated JavaScript, or using such input to construct free-form query objects (not simply using a string, but more like dropping an object into your BSON query). Both of these links should provide more information on the subject:
What type of attacks can be used vs MongoDB?
How does MongoDB address SQL or Query injection?

Can node.js execute JavaScript functions pulled from CouchDB like CouchApp does? How?

The quick overview is this: for my web app I can write most of my functionality using CouchApp and CouchDB views, etc. I love the feature of CouchApp that pushes my code up to the server via replication- this makes the deployment cycle very easy.
However, to do some arbitrary work not supported in couchdb and works around a few limitations, I need to put a web platform in front of CouchDB. I'm considering building this in node.js because it uses JavaScript and I want to continue the easy deployment method of pushing code into the database.
Here's how i imagine it working:
- I write a web server/service in node.js using the normal method and the node command to start it.
- this sevice connects to couch db and gets a virtual list and a URL mapping list. This list is stored in redis for quick lookup. This list will tell the server, when it gets a request, based on host and path, etc, which handler is to be run.
- the server fetches the handler- which is just a document, it could be a design document or an arbitrary json document in couchdb. And then executes that handler to handle the request, as if I'd writte the handler as part of node js.
So the question is, how to get a son data structure that contains a JavaScript function in it, in text form, and execute that function?
This may be blindingly obvious, but i come from a compiled background, so normally there would be a compilation step here that makes this pretty much impossible.
So, what I'm thinking is in pseudo code:
Var string thecode = getValueForMapKey(handlerFunctionIWant);
somehowmagicallyexecute(thecode)
Is there an exec or run function that will do the magical execution step above in JavaScript?
It will run in the node.js context.
You can also use it in node, like this, as a dynamic function:
var cradle = require('cradle');
var db = new(cradle.Connection)().database('db_name');
db.get('_design/node%2Fyour_code', function (err, doc) {
if (!err){
var your_code = new Function(doc['arguments'].join(','), doc.code);
your_code("cool", "also cool");
}else{
console.error('error:', err);
}
});
make your docs look like this:
{
"_id": "_design/node/your_code",
"arguments": [
"nameOfArg1",
"nameOfArg2"
],
"code": "console.log('arg1', nameOfArg1); console.log('arg2', nameOfArg2);"
}
It's in the same scope as where the new Function is called, so you have access to cradle, or you can require other libs, which will be loaded as if it was an anon function in that scope.
Put it in a design doc, then only admin can make changes, out of the box.
Here is a nicer, but similar approach:
// Format, in db:
doc = {
"_id": "_design/node",
"your_function_name": {
"arguments": [
"nameOfArg1",
"nameOfArg2"
],
"code": "console.log('arg1', nameOfArg1); console.log('arg2', nameOfArg2);"
},
"your_other_function_name": {
"arguments": [
"name"
],
"code": "console.log('hello', name, 'how\\'s it going, bro?');"
}
};
var cradle = require('cradle');
var db = new(cradle.Connection)().database('db_name');
function run_from_db(name, args){
db.get('_design/node', function (err, doc) {
if (!err){
if (doc[name] !== undefined){
var fn = new Function(doc[name]['arguments'].join(','), doc[name].code);
fn.apply(fn, args);
}else{
console.error("could not find", name, "in _design/node");
}
}else{
console.error(err);
}
});
}
run_from_db('your_other_function_name', ['konsumer']);
this will output:
hello konsumer how's it going, bro?
eval(handlerFunctionIwant) is the call to execute it. You need to make sure that there's no way for hackers to inject code into that string, of course.
It is not clear to me if this will evaluate it in a context that has access to other javescript resources, such as the rest of node.js or access to your couchdb library.

Categories

Resources