I know this will be something small I'm missing, but would appreciate the help.
Here is my test script (node.js)
var MongoClient = require('mongodb').MongoClient;
MongoClient.connect('mongodb://localhost:27017/myTestDB',
function (err, db) {
if (err)
debugger;
else {
db.collection('test', function (err, collection) {
collection.save({ name: "danny" }, function () { debugger;});
collection.find(function (err, results) {
if(results.items.length == 0){
///======> always = 0 !!!! WHY?!!!!
debugger;
}
});
});
}
db.close();
});
feel free to start your answer with "duh!"
UPDATE: you also need to move your db.close(); call inside the find callback or you're closing the connection before you're done with it.
In your example, results is a cursor, not an array of docs, so you need to call toArray on it to iterate over the cursor and get the array of docs. But you also need to put your find call inside the save callback. Otherwise the find is executing before the save has completed.
So something like this instead:
collection.save({ name: "danny" }, function () {
collection.find().toArray(function (err, results) {
// results contains the array of docs
// Now you can close the connection.
db.close();
});
});
Related
I'm having a problem with async Node.js module. In my Node.js app, I'm trying to get an array of JSON objects returned by a MongoDB request:
var fruits = ["Peach", "Banana", "Strawberry"];
var finalTab = [];
fruits.forEach(function(fruit) {
db.collection('mycollection').distinct("column1", {"column2":{$regex :fruit}}, (function(err, result) {
finalTab[fruit] = result;
console.log(result); // -> display the desired content
db.close();
if (err) throw err;
}));
});
console.log(finalTab); // -> []
At the moment, I'm at this point.
I'm trying to implement the async.map to iterate through Fruits collection.
https://caolan.github.io/async/docs.html#map
Can someone help? :)
Thanks by advance for help.
EDIT:
As I need all results returned by my db.collection functions, I'm trying to add these async commands to a queue, execute it and get a callback function.
You can try this:
async.map(fruits , function (fruit, callback) {
db.collection('mycollection').distinct("column1", {"column2":{$regex :fruit}}, (function(err, result) {
//here you are assigning value as array property
//finalTab[fruit] = result;
// but you need to push the value in array
finalTab.push(result);
console.log(result); // -> display the desired content
db.close();
if (err) throw err;
//callback once you have result
callback();
}));
}.bind(this), function () {
console.log(finalTab); // finally call
}, function (err, result) {
return Promise.reject(err);
});
const collect = [];
req.body.product.forEach(function(entry) {
mongoClient.connect(databaseServerUrl, function(err, db) {
let testCollection = db.collection('Tests');
testCollection.find({Product: entry}).toArray((err, docs) => {
let waiting = docs.length;
docs.forEach(function (doc) {
collect.push(doc);
finish();
});
function finish() {
waiting--;
if (waiting === 0) {
res.send(collect);
}
}
});
db.close();
});
});
this is only getting back the first set. If I have two nodes in my array of req.body.product for example. I am only getting back the first set. But I need to get back everything not just from one Collection.
Rather than performing two queries and combining the results into one array, I suggest performing a single query that gets all of the results, which would look something like this:
mongoClient.connect(databaseServerUrl, function(err, db) {
const query = { $or: req.body.product.map(Product => ({ Product })) };
db.collection('Tests').find(query).toArray((err, docs) => {
// ...handle `err` here...
res.send(docs);
db.close();
});
});
Note that I haven't tested this since I don't have a MongoDB database in front of me.
your mongoClient.connect() is asyncronous but your loop just execute without waiting for the callback.
Try async forEach loop: enter link description here
This should solve your problem
I am learning Node.js; due to asynchronous of Node.js I am facing an issue:
domain.User.find({userName: new RegExp(findtext, 'i')}).sort('-created').skip(skip).limit(limit)
.exec(function(err, result) {
for(var i=0;i<result.length;i++){
console.log("result is ",result[i].id);
var camera=null;
domain.Cameras.count({"userId": result[i].id}, function (err, cameraCount) {
if(result.length-1==i){
configurationHolder.ResponseUtil.responseHandler(res, result, "User List ", false, 200);
}
})
}
})
I want to use result in Cameras callback but it is empty array here, so is there anyway to get it?
And this code is asynchronous, is it possible if we make a complete function synchronous?
#jmingov is right. You should make use of the async module to execute parallel requests to get the counts for each user returned in the User.find query.
Here's a flow for demonstration:
var Async = require('async'); //At the top of your js file.
domain.User.find({userName: new RegExp(findtext, 'i')}).sort('-created').skip(skip).limit(limit)
.exec(function(err, result) {
var cameraCountFunctions = [];
result.forEach(function(user) {
if (user && user.id)
{
console.log("result is ", user.id);
var camera=null; //What is this for?
cameraCountFunctions.push( function(callback) {
domain.Cameras.count({"userId": user.id}, function (err, cameraCount) {
if (err) return callback(err);
callback(null, cameraCount);
});
});
}
})
Async.parallel(cameraCountFunctions, function (err, cameraCounts) {
console.log(err, cameraCounts);
//CameraCounts is an array with the counts for each user.
//Evaluate and return the results here.
});
});
Try to do async programing allways when doing node.js, this is a must. Or youll end with big performance problems.
Check this module: https://github.com/caolan/async it can help.
Here is the trouble in your code:
domain.Cameras.count({
"userId": result[i].id
}, function(err, cameraCount) {
// the fn() used in the callback has 'cameraCount' as argument so
// mongoose will store the results there.
if (cameraCount.length - 1 == i) { // here is the problem
// result isnt there it should be named 'cameraCount'
configurationHolder.ResponseUtil.responseHandler(res, cameraCount, "User List ", false, 200);
}
});
I try to find all documents from collection if it _id is not in array.
This is my code:
warehouses.find(query, items).toArray(function (error, docs) {
if (error) {
error(error);
return;
}
if (docs) {
var material = db.collection('material');
material.find({$nin: {'_id': docs[0].items}}, function (e, items) {
if (error) {
error(error);
return;
}
success(items);
});
}
});
in material.find line, currentItems have two ObjectsID, but the return of find is empty..What is wrong?
It is related to event-loop feature of nodejs. Each callback function is executed parallelly. So, while the line that starts with"material.find" started to be executed, probably
function (item, index) {
currentItems[index] = item._id;
}
is still being executed. This is why you get an empty result. To achieve your goal, you should done all work in only one callback function. Follow these steps:
select only ids in the first query(populate currentItems variable in the query). so, you can remove doc.items.foreach....
Then call the the function material.find.... inside callback function of the query.
thanks for your help...struggling big time with how to handle this properly. I'm in async now, having given up on my ability to write the callbacks properly. I have snippet where I'm passing a set of random numbers (eachrecord) and passing them through to a mongoose call. Trying to create a data set from the multiple queries I pass.
My issue is that no matter what I've done for 4 hours, the "newarray" variable is always empty.
Thank you for your help -
async.forEach(arLimit, function(eachrecord, callback){
newarray = new Array;
var query = UGC_DB_Model.find({}).skip(eachrecord).limit(-1);
query.execFind(function (err, data) {
if (err)
console.log(err);
else {
newarray.push(data);
}
});
callback(null, newarray);
}, function(err, result) {
if (err) return next(err);
console.log("(it's empty): " + result);
});
There are several issues with your code:
async.forEach isn't meant to 'generate' results, that's what async.map is for;
you need to call the callback only when execFind is done, and not immediately after calling it;
your newarray is probably not necessary;
So try this instead:
async.map(arLimit, function(eachrecord, callback){
var query = UGC_DB_Model.find({}).skip(eachrecord).limit(-1);
query.execFind(function (err, data) {
if (err)
callback(err); // pass error along
else {
callback(null, [ data ]);
// although I think you mean this (because 'data' is probably an array already)
// callback(null, data);
}
});
}, function(err, result) {
if (err) return next(err);
console.log("(it's empty): " + result);
});