Can I execute a raw MongoDB query in node-mongodb-native driver? - node.js

FYI - I know how to use the MongoDB driver and know this is not how one would use it in a web app, but this is not for a web app. My aim is to emulate the MongoDB shell in NodeJS
I'm writing a DB GUI and would like to execute a raw MongoDB query, eg db.tableName.find({ col: 'value' }). Can I achieve this using the native MongoDB driver? I'm using v2.2, which is current the latest version.
If not, how can I achieve this in NodeJS?

Note: The question has changed - see the updates below.
Original answer:
Yes.
Instead of:
db.tableName.find({ col: 'value' })
You use it as:
db.collection('tableName').find({ col: 'value' }, (err, data) => {
if (err) {
// handle error
} else {
// you have data here
}
});
See: http://mongodb.github.io/node-mongodb-native/2.2/api/Collection.html#find
Update
After you changed your question and posted some comments it is more clear what you want to do.
To achieve your goal of emulating the Mongo shell in Node you would need to parse the command typed by the user and execute the appropriate command while keeping in mind:
the difference between SpiderMonkey used by the Mongo shell and Node with V8 and libuv
the difference between BSON and JSON
the fact that Mongo shell works synchronously and the Node driver works asynchronously
The last part will probably be the hardest part for you. Remember that in the Mongo shell this is perfectly legal:
db.test.find()[0].x;
In Node the .find() method doesn't return the value but it either takes a callback or returns a promise. It will be tricky. The db.test.find()[0].x; case may be relatively easy to handle with promises (if you understand the promises well) but this will be harder:
db.test.find({x: db.test.find()[0].x});
and remember that you need to handle arbitrarily nested levels.
The Mongo protocol
After reading some of the comments I think it's worth noting that what you actually send to the Mongo server has nothing to do with the JavaScript that you write in the Mongo shell. The Mongo shell uses SpiderMonkey with a number of predefined functions and objects.
But you don't actually send JavaScript to the Mongo server so you can't send things like db.collection.find(). Rather you send a binary OP_QUERY struct with a collection name encoded as a cstring and a query encoded as BSON plus a bunch of binary flags. See:
https://docs.mongodb.com/manual/reference/mongodb-wire-protocol/#wire-op-query
The BSON is itself a binary format with a number of low level values defined as bytes:
http://bsonspec.org/spec.html
The bottom line is that you don't send to the Mongo server anything resembling what you enter in the Mongo shell. The Mongo shell parses the things that you type using the SpiderMonkey parser and sends binary requests to the actual Mongo server. The Mongo shell uses JavaScript but you don't communicate with the Mongo server in JavaScript.
Example
Even the JSON query object is not sent to Mongo as JSON. For example, when you are searching for a document with a hello property equal to "world" you would use {hello: 'world'} in JavaScript or {"hello": "world"} in JSON but this is what gets send to the Mongo server - by the Mongo shell or by any other Mongo client:
\x16\x00\x00\x00\x02hello\x00\x06\x00\x00\x00world\x00\x00
Why it's so different
To understand why the syntax used in Node is so different from the Mongo shell, see this answer:
Why nodejs-mongodb middleware has different syntax than mongo shell?

Related

Synchronous monk mongodb query in nodejs

I am working with monk mongodb query in my nodejs application, when I execute the query I get the response asynchronously in a callback mechanism.
I want to wait for the query to execute and use the result.
The code
var mycoll = db.get('collection_name');
mycoll.find({"key":123},function(e,docs){
result=docs[0].arr[n]
});
Here arr is the array of numbers in a document, n is changing constantly thus asynchronous way gives wrong answer.
Can someone modify the code and guide me through.

MongoDB does not seem to behave how it should as a whole

When I first used MongoDB I managed to connect successfully, however then I wanted to carry out the most basic query such as:
db.users.find()
I got an error saying TypeError: Cannot read property 'find' of undefined
Basically meaning I cannot use a collection as a property to the object db.
So i tried this:
var user_col = db.collection('users');
user.col.find();
which works absolutely fine.
Over the last few days I have kept having to look up other ways of doing things as the standard documented way doesn't seem to work. Just now I wanted to get the total users on the app, so like it says in the documentation I should do this:
var count = db.runCommand( { count: 'users' } );
console.log(count);
however this gave the error:
TypeError: undefined is not a function
Is there a problem with MongoDB you have seen like this before or am I just being stupid? I do not want to have to keep finding other, less efficient ways of doing things so finally I ask here what is going on.
Thank you.
It appears you are confusing the Mongo shell API with the node.js native driver API. While both are JavaScript, the shell is sync while node.js is async so they're totally different.

Executing REDIS Command in Node.js

I am writing a Node app. This app interacts with a REDIS database. To do that, I'm using node_redis. Sometimes, I want to just execute a command using a line of text. In other words, I want to do a pass through without using the wrapper functions. For instance, I may have:
set myKey myValue
I would LOVE to be able to just execute that without having to break apart the text and call client.set('mykey', 'myValue'); Is there a way to just execute a command like that against REDIS in the Node world? If so, how?
Thanks!
You should be able to use client.send_command(command_name, args, callback) to send arbitrary commands to redis. Args can be empty and so in your case you would just call client.send_command('set myKey myValue', null, cb).

how can i use common-node with mongo-sync in my nodejs?

i found the plugin mongo-sync which can make me to use mongoDB synchronized
on the git,there show :
It is a thin wrapper around the official MongoDB driver for Node. Here is a quick usage example that you can use with Common Node:
var Server = require("mongo-sync").Server;
var server = new Server('127.0.0.1');
var result = server.db("test").getCollection("posts").find().toArray();
console.log(result);
server.close();
how can i use like this?
it's mentioned that use with Common Node
whether it's means common-node?
so, how can i use it ? or use mongo-sync straightforwardly?
It means you have to follow Common-Node installation instructions and use common-node command instead of the plain-old node to run your program.
As the docs mention, to use it with plain-old node you need to use node-fibers and make queries inside a Fiber.
No way around node-fibers I'm afraid, as mongo-sync is just a "synchronous" wrapper around asynchronous mongo driver, and it's hard to make async js code synchronous without some low level monkey-patching.

Mongoose and commander

I'm writing some scripts for some command-line manipulation of Mongoose models with commander.js (eventually, I'd like to run these tools using Cron).
Now, I've written several scripts with commander and they all work fine, but if I connect to the MongoDB database using mongoose, they script just hangs after it's done. Now, I figured the database connection is keeping node alive, so I added a mongoose.disconnect() line and it still hangs.
The only thing I found that allows me to shutdown is to use process.exit(), but I'm reluctant to just terminate the process. Is there something in particular that I should do to trigger a graceful shutdown?
My reading of the API docs implies that .disconnect() must be given a callback function. It looks like it's called for each that's disconnected and may be passed an error.
There is a check in the code to make sure it's not called if it doesn't exist when things work out, but that check isn't being run on errors, so if Mongoose received an error message from the MongoDB client, it may be leaving a connection open and that's why it's not stopping execution.
If you're only opening a single connection to the database, you may just want to call [Connection object].close() since that function correctly inserts a no-op "callback" if no callback is given, and looks like it will correctly destruct things.
(The more I look into Mongoose, the more I want to just write a thin wrapper around the MongoDB client so I don't have to deal with Mongoose's "help.")
I use the async "Series" to perform operations and then call mongoose.connection.close() on completion. It prevents callback hell and allows you to neatly perform operations either one at a time or parallel followed by a function when all the other methods have completed. I use it all the time for scripts that require mongoose but are meant to terminate after all mongoose operations are finished.
Shutdown the node program directly is hiding the symptoms, not fixing the problem!
I finally isolated the problem and found it to be with Mongoose schema definitions. If you try to shutdown the connection too soon after Mongoose schemas are defined1, the application hangs and eventually produces some weird MongDB-related error.
Adding a small timeout before running the program.parse(argv) line to run the commander application fixes the problem. Just wrap the code like so:
var program = require('commander')
, mongoose = require('mongoose')
, models = null
;
// Define command line syntax.
program
.command(...)
;
mongoose.connect(
..., // connection parameters.
function() {
// connected to database, defined schemas.
models = require('./models');
// Wait 1 second before running the application code.
setTimeout(function(){
program.parser(process.argv);
}, 1000);
}
);
1: This is my initial interpretation, I have not (yet) extensively tested this theory. However, removing Mongoose schema definitions from the application successfully prevents the application from hanging.
Actually, just using process.nextTick() instead of the setTimeout() call fixes the situation nicely!

Resources