Connecting to MongoDB Successfully, But Having Issues with `getCollection()` - node.js

I am writing some tests for a Node/Mongo project, and in one of my tests I need to connect to the database, and then pull a document from my jobs collection. However, I am running into an issue. I can connect to the database successfully, but then get an error on my findOne(). The specific error is:
TypeError: db.getCollection is not a function
Here is the code:
const MongoClient = require('mongodb').MongoClient;
const url = 'mongodb://localhost:27017';
const dbName = 'sample_db';
// Create a new MongoClient
const client = new MongoClient(url);
client.connect(async function (err) {
assert.equal(null, err);
console.log("Connected successfully to server"); // I see this in the console
const db = await client.db(dbName);
let savedJobResult = await db.getCollection("jobs").findOne({
"name": "Agenda Job Test"
});
console.log('savedJobResult: ', savedJobResult);
client.close();
});
What am I missing here?

Try this query
let savedJobResult = await db.collection("jobs").findOne({
"name": "Agenda Job Test"
});

change getCollection to collection
const insertDocuments = function(db, callback) {
// Get the documents collection
const collection = db.collection('documents');
// Insert some documents
collection.insertMany([
{a : 1}, {a : 2}, {a : 3}
], function(err, result) {
assert.equal(err, null);
assert.equal(3, result.result.n);
assert.equal(3, result.ops.length);
console.log("Inserted 3 documents into the collection");
callback(result);
});
}

Related

Output data from mongodb to an external variable

How to output data from mongodb to an external variable. For example
let variableArr = [];
const mongoClient = new MongoClient(url, { useUnifiedTopology: true });
mongoClient.connect(function(err, client){
const db = client.db("variabledb");
const collection = db.collection("variables");
if(err) return console.log(err);
collection.find().toArray(function(err, results){
results.forEach(item => variableArr.push(item))
client.close();
});
console.log(variableArr);
The console outputs an empty array. I understand that the problem is async, but how to implement this moment.
Thanks!

Node mongodb driver can insert, count, but find

I am migrating an existing app to mongodb,
I have this code mostly found on the node native mongodb driver site.
var fs = require('fs-extra');
var MongoClient = require('mongodb').MongoClient;
const mongoConfig = JSON.parse(fs.readFileSync("./configuration/mongo.json", "utf-8").toString());
const assert = require('assert');
const insertDocuments = function(db, callback) {
// Get the documents collection
const collection = db.collection('documents');
// Insert some documents
collection.insertMany([
{a : 1}, {a : 2}, {a : 3}
], function(err, result) {
assert.equal(err, null);
assert.equal(3, result.result.n);
assert.equal(3, result.ops.length);
console.log("Inserted 3 documents into the collection");
callback(result);
});
};
const findDocuments = function(db, callback) {
// Get the documents collection
const collection = db.collection('documents');
// Find some documents
collection.find({}).toArray(function(err, docs) {
assert.equal(err, null);
console.log("Found the following records");
console.log(docs)
callback(docs);
});
};
function initDb() {
var uri = "mongodb://" + mongoConfig.user + ":" + mongoConfig.pass + "#" + mongoConfig.host + ":" + mongoConfig.port;
MongoClient.connect(uri, {auth: {user: mongoConfig.user, password: mongoConfig.pass}, authSource: mongoConfig.dbname}, function (err, client) {
if (err) {
console.error(err);
}
const db = client.db('test');
insertDocuments(db, function() {
findDocuments(db, function() {
client.close();
});
});
}
initDb();
Then i get the following output in the console :
Inserted 3 documents into the collection
Found the following records
[]
Using Robomongo from the same computer to the same server using same credentials, i am able to see and edit the datas.
the insert is working fine, as i am writing this i have a dozen of test documents inserted this way.
But find allways return an empty array.
However, using count instaed of toArray returns the corret value.
I am using :
"mongodb": "^3.0.5",
From my package.json
What am i missing pls ?

Uploading a doc file Directly in Mongodb

I want to save and retrieve a Word doc and PDF file with a size of 1 MB, directly in MongoDB with Node.js. How can I do this is there any article explain about it or can some one help me on this.
Here is the standalone node js code to save the file as binary data in MongoDB. As the maximum file size is 1MB, you can save it in normal collection rather than GridFs.
This can be extended to run as web apps using "express" or "hapi" frameworks. You may need to refer the respective tutorial for that.
Save the file as binary data in MongoDB:-
Note: I have the sample file in "docs" directory. So, I have prefixed it with docs (i.e. "/docs/testplan.docx"). You can remove that if you don't need it.
var MongoClient = require('mongodb').MongoClient;
var Binary = MongoClient.Binary;
var fs = require('fs');
var assert = require('assert');
var url = 'mongodb://localhost:27017/test';
var binaryFileData = fs.readFileSync(__dirname + "/docs/testplan.docx");
var insertDocument = function(db, callback) {
db.collection('file_save').insertOne( {
"fileName" : "testplan.docx",
"fileData" : binaryFileData
}, function(err, result) {
assert.equal(err, null);
console.log("Inserted a document into the collection.");
callback();
});
};
MongoClient.connect(url, function(err, db) {
assert.equal(null, err);
insertDocument(db, function() {
console.log("Closing the database connection...")
db.close();
});
});
Read the file data and save it to disk:-
var MongoClient = require('mongodb').MongoClient;
var Binary = MongoClient.Binary;
var fs = require('fs');
var assert = require('assert');
var url = 'mongodb://localhost:27017/test';
var findDocument = function (fileName, db, callback) {
db.collection('file_save').findOne({"fileName" : fileName }, function (err, document) {
assert.equal(null, err);
console.log(document.fileName);
fs.writeFileSync("testplan_out.docx", document.fileData.buffer);
console.log("File has been written to disk");
callback();
});
};
MongoClient.connect(url, function (err, db) {
assert.equal(null, err);
findDocument("testplan.docx", db, function () {
db.close();
});
});
that works perfectly alright! But I'm trying to upload the document from the POSTMAN and I'm developing my project with MEAN stack.
//document-model.js
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
var documentSchema = {
docFile: {
type: String
}
};
mongoose.model('FileDocument', documentSchema);
//document-route.js
var express = require('express'),
documentRoute = express.Router(),
document = require('../controllers/document-controller');
documentRoute.post('/upload', document.uploadDocument);
module.exports = documentRoute;
//document-controller.js
var document = {
uploadDocument: function (req, res) {
var fileDocument = new FileDocument({
docFile: req.body.docFile
});
fileDocument.save(function (err, result) {
if (err) {
res.status(500).send(err);
} else {
res.status(200).send('Document Uploaded Successfully');
}
});
}
};
I was trying in this way but it is not uploading to mongodb the result is gives in the mongo shell.
{ "_id" : ObjectId("59693872b8b83f42b42a3b9f"), "docFile" : "", "__v" : 0 }

NodeJS With Mongo: Callback Is Not A Function error

Im currently working on a NodeJS/Mongo project where I need to pull all the documents from a collection. I currently have the following code written:
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,
assert = require('assert');
var server = new Server('[server]', 27017);
var authDB = new Db('admin', server);
var DB1250 = new Db('1250', server);
var findDocuments = function (callback) {
authDB.authenticate("Username", "Password");
DB1250.open(function (error, db) {
if (error) {
console.log(error);
}
else {
console.log("successfully accessed: ", db);
callback;
var cursor = db.collection('Patients').find();
console.log('cursor ', cursor);
cursor.forEach(function (error, document) {
if (error) {
console.log('Document does not exist. Error: ', error);
}
else {
console.log('Document: ', document);
}
});
}
});
};
findDocuments(function (data) {
});
I am able to authenticate/connect to the server, connect to the DB, and connect to the collection. When I enter the forEach loop to iterate through all the documents, I keep getting the error "Callback is not a function". Can you guys see what I am doing wrong?
I believe the cursor you have there has not resolved into an array, so forEach is not a valid method. You might be looking for eachAsync, which will wait for the query to return before iterating.
Alternatively, you can wait for the query promise to resolve, ie:
cursor.then(docs => docs.forEach(callback));
which I personally find a little clearer.
Heres the solution I came up with after using Mongoose:
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,
Mongoose = require('mongoose');
assert = require('assert');
var findDocuments = function (callback) {
var options = { server: { socketOptions: { keepAlive: 1000 } } };
var connectionString = 'mongodb://username:password#server:27017/admin';
// Connected handler
Mongoose.connect(connectionString, function (err) {
var db = Mongoose.connection.useDb('db');
var collection = db.collection("collection");
collection.find().stream()
.on('data', function (document) {
console.log(document);
})
.on('error', function (err) {
// handle error
console.log(err);
})
.on('end', function () {
// final callback
});
});
// Error handler
Mongoose.connection.on('error', function (err) {
console.log(err);
});
// Reconnect when closed
Mongoose.connection.on('disconnected', function () {
self.connectToDatabase();
});
};
findDocuments(function () {
db.close();
});
cursor.forEach() is an asynchronous operation but returns nothing. So you shouldn't do db.close() or likewise below the line somethere synchronously.
Besides; I am not sure which version Node driver you are refering to but in the recent ones like v3+ cursor.forEach() doesn't take an error first type callback like the one that you use in your code. It will take an "iterator" and an "end" callback such as;
cursor.forEach(doc => console.log(doc),
err => err ? console.log(err)
: db.close())
So the above code will just work fine, iterating and processing the documents one by one as they appear without waiting up until all of them have been retrieved to the memory.

MongoDB - running parallel queries with nodejs driver and close the db connection when the last query completes

I need to run several queries against MongoDB in parallel using the node.js driver.
Currently I am using a counter which gets decreased any time a query gets completed. When the counter reached 0 it means that all queries have completed and then I close the db connection.
In a simple case with 2 queries running in parallel the code is the following
var mongodb = require('mongodb');
var MongoClient = require('mongodb').MongoClient;
var db;
MongoClient.connect("mongodb://localhost:27017/company", function(err, database) {
if(err) throw err;
db = database;
let collection = "resumes";
let numberOfParallelQueries = 2;
let result = [];
let finalCallback = (err, resp) => {
if (err) throw(err);
numberOfParallelQueries = numberOfParallelQueries -1;
result.push(resp);
if (numberOfParallelQueries == 0) {
console.log(result);
db.close()
};
}
db.collection(collection).find({"jobs": {$elemMatch: {"company": "CNA", position: "director"}}}).toArray(finalCallback);
db.collection(collection).find({$and: [{"jobs.company": "CNA"}, {"jobs.position": "director"}]}).toArray(finalCallback);
});
My question is whether there any more elegant solution. I am thinking about something in the line of forkJoin() method of Observable.
Thanks in advance
That's what Promises are for:
var mongodb = require('mongodb');
var MongoClient = require('mongodb').MongoClient;
var db;
MongoClient.connect("mongodb://localhost:27017/company", function(err, database) {
if(err) throw err;
db = database;
let collection = "resumes";
Promise.all([
queryPromise(collection, {"jobs": {$elemMatch: {"company": "CNA", position: "director"}}}),
queryPromise(collection, {$and: [{"jobs.company": "CNA"}, {"jobs.position": "director"}]})
]).then(function(result) {
// result is an array of responses here
db.close();
}).catch(function(err) {
console.log(err);
db.close();
});
function queryPromise(collection, query) {
return new Promise(function(resolve, reject) {
db.collection(collection).find(query).toArray(function(err, resp) {
if (err) {
reject(err);
} else {
resolve(resp);
}
});
})
}
});
using async/await is more simpler
var mongodb = require('mongodb');
var MongoClient = require('mongodb').MongoClient;
var db;
MongoClient.connect("mongodb://localhost:27017/company", function(err, database) {
if(err) throw err;
db = database;
let collection = "resumes";
let queries = [];
queries.push(async()=>await db.collection(collection).find({"jobs": {$elemMatch: {"company": "CNA", position: "director"}}}).toArray());
queries.push(async()=>await db.collection(collection).find({$and: [{"jobs.company": "CNA"}, {"jobs.position": "director"}]}).toArray());
Promise.all(
queries
).then(function(result) {
// result is an array of arrays of queries responses here
db.close();
}).catch(function(err) {
console.log(err);
db.close();
});
});

Resources