Callback function running unexpectedly - node.js

There is a small code i have written below and issue is explained within comments. Problem is with the bold callback function while creating the collection. There is an error while creating the collection and the message should be displayed as soon as the main function for creating the collections is ending but message appears randomly as seen in the output below:
It is called unexpected on line marked with question mark. I am running this js file on node.js and mongoDB environment.
Thanks.
var mongo = require("mongodb");
var Db = mongo.Db;
var mongoC = mongo.MongoClient;
var assert = require('assert');
mongoC.connect("mongodb://localhost:27017/social", {
native_parser: true
}, function (err, db) {
if (!err) {
console.log("We are Connected!\n");
//creating the Collection
db.createCollection("node", {
strict: true
}, function (err, coll) {
if (!err) {
console.log("*********Collection Created Succesfully*********");
console.log("Collection created Successfully\n" + JSON.stringify(coll) + "\n-------------------\n");
}
else{
console.log("Cannot create Collection because " + err);
}
});
//Collection created now
console.log("*********************************inserting documents in the selected collection***********************");
var coll = db.collection('node');
var doc1 = {"name":"doc1","age":26};
var manydocs = [{"name":"doc2","age":45},{"name":"doc3","age":19}];
//coll.insert(doc1,{w:1},function(err,result){if(err){console.log("Error while inserting doc1 " + err);}else{console.log(result);}});
//coll.insert(manydocs,{w:1},function(err,result){if(err){console.log("Error while inserting manydocs " + err);}});
console.log("***************************documents are now updated successfully***********************************");
console.log("*******************Now let us update the documents*******************");
var query = {"name": "doc1"};
var update= {$set : {"age":86}};
//coll.update(query,update,function(err,result){if(!err){console.log(result + "'s age has been successfully update to " + result);}});
console.log("***************Docments updated");
console.log("*******************Querying the items**************************");
coll.find().each(function(err,myDoc){console.dir(myDoc);console.dir("hey");});
//coll.findOne(query,function(err,result){});
var stream = coll.find(query).stream();
stream.on("data",function(item){console.log(item._id);});
stream.on("end",function(){});
}
else {
console.log("Cannot connect because : " + err);
}
});
Below is the output.
We are Connected!
*********************************inserting documents in the selected collection***********************
***************************documents are now updated successfully***********************************
*******************Now let us update the documents*******************
***************Docments updated
*******************Querying the items**************************
Cannot create Collection because Error: Collection node already exists. Currently in strict mode.

You should work on node collection inside the db.createCollection's callback:
UPDATE: run this code:
var mongo = require("mongodb");
var Db = mongo.Db;
var mongoC = mongo.MongoClient;
var assert = require('assert');
mongoC.connect("mongodb://localhost:27017/social", {
native_parser: true
}, function (err, db) {
if (!err) {
console.log("We are Connected!\n");
//creating the Collection
db.createCollection("node", {
strict: true
}, function (err, coll) {
if (!err) {
console.log("*********Collection Created Succesfully*********");
console.log("Collection created Successfully\n" + JSON.stringify(coll) + "\n-------------------\n");
//Collection created now
console.log("*********************************inserting documents in the selected collection***********************");
var doc1 = {
"name": "doc1",
"age": 26
};
var manydocs = [{
"name": "doc2",
"age": 45
}, {
"name": "doc3",
"age": 19
}];
//coll.insert(doc1,{w:1},function(err,result){if(err){console.log("Error while inserting doc1 " + err);}else{console.log(result);}});
//coll.insert(manydocs,{w:1},function(err,result){if(err){console.log("Error while inserting manydocs " + err);}});
console.log("***************************documents are now updated successfully***********************************");
console.log("*******************Now let us update the documents*******************");
var query = {
"name": "doc1"
};
var update = {
$set: {
"age": 86
}
};
//coll.update(query,update,function(err,result){if(!err){console.log(result + "'s age has been successfully update to " + result);}});
console.log("***************Docments updated");
console.log("*******************Querying the items**************************");
coll.find().each(function (err, myDoc) {
console.dir(myDoc);
console.dir("hey");
});
//coll.findOne(query,function(err,result){});
var stream = coll.find(query).stream();
stream.on("data", function (item) {
console.log(item._id);
});
stream.on("end", function () {});
} else {
console.log("Cannot create Collection because " + err);
}
});
} else {
console.log("Cannot connect because : " + err);
}
});

Related

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 ?

How to query data from mongoDB with moongoose in nodejs

I only want to check if the key exist in the databse but when i try to query it I only get NULL.
This is my invite.js
var mongoose = require('mongoose');
mongoose.createConnection('mongodb://localhost/invitation');
var db2 = mongoose.createConnection;
// User Schema
var InvitationSchema = mongoose.Schema({
key: {
type: String,
index: true
},
used: {
type: String
}
});
var Invitation = module.exports = mongoose.model('Invitation', InvitationSchema);
module.exports.getUsedByKey = function(id, callback){
var query = {used: key};
Invitation.findById(query, callback);
};
module.exports.getInvitationByKey = function(key, callback){
var query = {key: key};
Invitation.findOne(query, callback);
console.log('keythingy ' + callback);
};
And this is how I try to use that function:
function checkKey(key, res) {
Invitation.getInvitationByKey(key, function(err, key2) {
//console.log('key: ' + key + '\nkey2: ' + key2.key)
if (err) throw err;
if (key2 !=null) {
return key2.key;
} else {
return false;
}
})
}
Use the below best way for write code in NodeJS. Mongoose.
Make one JavaScript class for connection with mongodb like --> db.js
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/invitation');
var Schema = mongoose.Schema;
// User Schema
var InvitationSchema = mongoose.Schema({
key: {
type: String,
index: true
},
used: {
type: String
}
}, {
collection: 'Invitation'
});
module.exports.Invitation = mongoose.model('Invitation', InvitationSchema);
Make another fetch data from collection JavaScript class --> invitation.js
var db = require('db.js');
module.exports.Initation = {
getInvitationByKey : function(key, callback) {
var query = {key: key};
db.Invitation.findOne(query, function(err, result){
console.log("Result : ", result, ", Error : ", err);
callback(err, result);
});
}
}
Make route JavaScript class --> invitation_route.js
var express = require('express');
var router = express.Router();
var invitation = require('invitation.js').Initation;
router.get('/get/:key', function(req, res, next) {
invitation.getInvitationByKey(req.params.key, function(err, result){
if (err) {
console.log(' Error : ', err);
res.body(err);
} else {
console.log(' Result : ' + JSON.stringify(result));
res.send(result);
};
});
});

Mongodb count not calling callback

I have following code in my nodejs app:
db.open(function(err, db) {
while (item = stream.read())
{
var parsedDate = parseDateFromString(item.title);
var movieName = parseNameFromString(item.title);
var channelName = parseChannelFromString(item.title);
//var doc = { "name": movieName, "channel": channelName, "showed": parsedDate, "showDate": parsedDate.format(), "run_id": new Date().toString()};
var doc = { "name": movieName, "channel": channelName, "showed": parsedDate, "run_id": new Date().toString()};
db.collection('programs', function(err, collection) {
collection.find({'name' : doc.name, "channel" : doc.channel}).count(function(countErr, count) {
console.log('count!');
if(count == 0)
insertDocument(collection, doc);
else
console.log('Found match from db with name ' + matchDoc.name);
});
});
} // End of while
}); // End of Open
Problem is that count! is never reported. So collection.count is not calling its callback. I checked that collection.find is called multiple times. What could cause that problem?

How to rename/alias field(s) while fetching it from MongoDB through query using MongoDB-Node.JS native drive?

Consider the following code, which I am using to fetch the data from my local MongoDB 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,
Code = require('mongodb').Code,
BSON = require('mongodb').pure().BSON,
assert = require('assert');
var db = new Db('test', new Server('localhost', 27017));
db.open(function(err, db) {
db.createCollection('simple_limit_skip_find_one_query', function(err, collection) {
assert.equal(null, err);
collection.insert([{a:1, b:1}, {a:2, b:2}, {a:3, b:3}], {w:1}, function(err, result) {
assert.equal(null, err);
collection.findOne({a:1}, {fields:{b:1}}, function(err, doc) {
// I got the read document in the object 'doc'
});
});
});
});
Now, I want to rename a field name while retrieving only (not in the DB), for example with the above code, I have a field named b in the returned object doc I want it to be baseID instead of b
Is there any way to do it?
Note: I cannot take action on the retrieved object doc to rename field like JSON key renaming. I want it to be queried and MongoDB will the same.
Use aggregate framework of MonogDB (But you need to upgrade the MongoDB server instance to >= 2.1).
The following is the soultion for the above example
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,
Code = require('mongodb').Code,
BSON = require('mongodb').pure().BSON,
assert = require('assert');
db.open(function (err, db) {
if (err) console.dir(err);
db.createCollection('simple_limit_skip_find_one_query', function (err, collection) {
if (err) console.dir(err);
collection.insert([{ a: 1, b: 1 }, { a: 2, b: 2 }, { a: 3, b: 3}], { w: 1 }, function (err, doc) {
if (err) console.dir(err);
collection.aggregate([
{ $project: {
a: 1,
_id:0,
baseID: "$b"
}
}
], function (err, doc) {
if (err) console.dir(err);
console.log(doc);
});
});
});
});
Output:
[ { a: 1, baseID: 1 },
{ a: 2, baseID: 2 },
{ a: 3, baseID: 3 }]

mongo-db error while trying to get document by id

I have this mongo-db.js file:
var MongoClient = require('mongodb').MongoClient,
ObjectID = require('mongodb').ObjectID;
exports.MongoDB = function() {
this.DB_NAME = "myDBNAME";
this.MongoClient = MongoClient;
return this;
};
exports.MongoDB.prototype.openDB = function(action) {
console.log("Open DB");
var scope = this;
this.MongoClient.connect(this.generateMongoUrl(), function(err, db) {
if (!err) {
console.log("Open DB Success");
if (action && typeof action === "function") {
action(db, scope);
}
} else {
console.log("DB Connect Error: " + err);
}
});
};
exports.MongoDB.prototype.closeDB = function(db, action) {
var scope = this;
return function() {
console.log("Close DB and apply action with arguments");
db.close();
action.apply(this, arguments);
};
};
exports.MongoDB.prototype.getItemById = function(id, callback) {
this.openDB(function(db, scope) {
console.log("Retrieving item: " + id);
db.collection("items", function(err, collection) {
if (err) { callback(err); }
else {
collection.findOne({ _id: ObjectID.createFromHexString(id) }, scope.closeDB(db, callback));
}
});
});
};
exports.MongoDB.prototype.getAllItems = function(callback) {
this.openDB(function(db, scope) {
console.log("Retrieving all items");
db.collection("items", function(err, collection) {
if (err) { callback(err); }
else {
collection.find({ }).toArray(scope.closeDB(db, callback));
}
});
});
};
And I run the following:
var scope = this;
var _items = [];
var counter = 0;
var done = function() {
console.log("done!");
};
var getItem = function(error, item) {
if (error) { }
else {
console.log("done loading item " + item._id);
_items.push(item);
if (_items.length === counter) {
done();
}
}
};
this.db.getAllItems(function(error, items) {
if (error) { }
else {
for (var i = 0; i < items.length; i++) {
var id = items[i]._id;
if (id) {
counter++;
console.log("load item " + id);
scope.db.getItemById(id, getItem);
}
}
}
});
When running this code I get:
Open DB
Open DB Success
Retrieving all items
Close DB and apply action with arguments
load item 50fb26263d47b70000000001
Open DB
load item 50fb277f172a5d0000000001
Open DB
load item 50fb2aa7865d870000000001
Open DB
load item 5102b7ddfe581ce5c7000001
Open DB
load item 5109678839aefde9fe000001
Open DB
load item 51096a91d0b50572ff000001
Open DB
load item 51096b06405d398bff000001
Open DB
load item null
Open DB
load item 51098b6b58bc1d0000000001
Open DB
load item 51098e16fb0e710000000001
Open DB
load item 51098e31a725100000000001
Open DB
load item 510991f20bc7690000000001
Open DB
load item 51099261258c710000000001
Open DB
load item 5109928b7edf7a0000000001
Open DB
load item 510992f0c73ccc0000000001
Open DB
load item 51099336e8a0090000000001
Open DB
load item 5109938d5fc9ce0000000001
Open DB
load item 510993cc8159610000000001
Open DB
load item 51099530ab74fb0000000001
Open DB
load item 5109956e8b059e0000000001
Open DB
load item 510995965f38da0000000001
Open DB
load item 510995ca14c0610000000001
Open DB
load item 5109963f2acd750000000001
Open DB
load item 5109966fc7001b0000000001
Open DB
Open DB Success
Retrieving item: 5109928b7edf7a0000000001
/myproj/node_modules/mongodb/lib/mongodb/connection/server.js:481
throw err;
^
Error: Argument passed in must be a single String of 12 bytes or a string of 24 hex characters
at Function.createFromHexString (/myproj/node_modules/mongodb/node_modules/bson/lib/bson/objectid.js:212:11)
at exports.MongoDB.getItemById (/myproj/js/mongo-db.js:95:52)
at Db.collection (/myproj/node_modules/mongodb/lib/mongodb/db.js:496:44)
at exports.MongoDB.getItemById (/myproj/js/mongo-db.js:92:12)
at exports.MongoDB.openDB (/myproj/js/mongo-db.js:72:17)
at MongoClient.connect (/myproj/node_modules/mongodb/lib/mongodb/mongo_client.js:112:5)
at _finishConnecting (/myproj/node_modules/mongodb/lib/mongodb/db.js:2126:7)
at Db.open (/myproj/node_modules/mongodb/lib/mongodb/db.js:249:14)
at Server.connect.connectCallback (/myproj/node_modules/mongodb/lib/mongodb/connection/server.js:277:7)
at g (events.js:192:14)
When I put console.log(typeof id); before Object.createFromHexString(...), I get Object.
Trying to change the id by doing id=id+""; made the same error.
Why do I get this error?
When using the MongoClient, the documents returned contain BSON ObjectID values and not strings. A BSON ObjectId using the native MongoClient has a structure like:
_id = {
id : "{12 bytes of binary data}",
_bsontype : "ObjectID"
}
So, if you try to run it on the createFromHexString method, it will crash, as it's already a BSON ObjectID.
Here's a simple example showing how no conversion is necessary from the Id that was returned originally.
var
mongodb = require('mongodb'),
MongoClient = mongodb.MongoClient;
MongoClient.connect("mongodb://localhost:27017/default?w=1", function (err, db) {
db.collection("research").find({}, {'_id' : 1}).toArray(function(err, results) {
results.forEach(function(doc) {
console.log(doc._id + " type " + typeof doc._id);
// now async get all docs
db.collection("research").findOne({'_id': doc._id}, function(err, doc) {
console.log("# " + doc._id);
console.log(doc);
});
});
});
});

Resources