NodeJS / Mongo: combining a request through various collections

I am looking for a loop to query through various collections using MongoDB using NodeJS Driver . For this test, I used the sample code from findOne docs to insert a bunch of documents into various collections:

collection.insertMany([{a:1, b:1}, {a:2, b:2}, {a:3, b:3}], {w:1}, function(err, result) { test.equal(null, err); 

Creation of different collections at the same time (each collection has at least one copy of previously inserted documents):

  • test
  • test1
  • test2
  • test3
  • test4
  • test6
  • test10

And I want to compile a list of the collection that I have in the database ( 'test' in my case):

 var MongoClient = require("mongodb").MongoClient, test = require("assert"); MongoClient.connect("mongodb://localhost:27017/test", function(err, db) { db.listCollections().toArray(function(err, items) { test.ok(items.length >= 1); console.log(items); db.close(); }); }); 

And a list of the previously mentioned collections appears. So far, everything is in order! I can even skip the array to get only the name of the collections:

 var MongoClient = require("mongodb").MongoClient, test = require("assert"); MongoClient.connect("mongodb://localhost:27017/test", function(err, db) { db.listCollections().toArray(function(err, items) { test.ok(items.length >= 1); items.forEach(c => { console.log(c.name); }); db.close(); }); }); 

Again no problem! But when I then try the request in a loop:

 var MongoClient = require("mongodb").MongoClient, test = require("assert"); MongoClient.connect("mongodb://localhost:27017/test", function(err, db) { db.listCollections().toArray(function(err, items) { test.ok(items.length >= 1); items.forEach(c => { var collection = db.collection(c.name); collection.findOne({ a: 2 }, { fields: { b: 1 } }, function(err, doc) { console.log(doc); }); }); }); db.close(); }); 

I get:

 null null null null null null null 

Although the loop to get the collection seems to work fine:

 var MongoClient = require("mongodb").MongoClient, test = require("assert"); MongoClient.connect("mongodb://localhost:27017/test", function(err, db) { db.listCollections().toArray(function(err, items) { test.ok(items.length >= 1); items.forEach(c => { var collection = db.collection(c.name); console.log(collection); }); }); db.close(); }); 

Output Example:

 Collection { s: { pkFactory: { [Function: ObjectID] index: 10866728, createPk: [Function: createPk], createFromTime: [Function: createFromTime], createFromHexString: [Function: createFromHexString], isValid: [Function: isValid], ObjectID: [Circular], ObjectId: [Circular] }, db: Db { domain: null, _events: {}, _eventsCount: 0, _maxListeners: undefined, s: [Object], serverConfig: [Getter], bufferMaxEntries: [Getter], databaseName: [Getter] }, topology: Server { domain: null, _events: [Object], _eventsCount: 8, _maxListeners: undefined, clientInfo: [Object], s: [Object] }, dbName: 'test', options: { promiseLibrary: [Function: Promise], readConcern: undefined, readPreference: [Object] }, namespace: 'test.test2', readPreference: ReadPreference { _type: 'ReadPreference', mode: 'primary', tags: undefined, options: undefined }, slaveOk: true, serializeFunctions: undefined, raw: undefined, promoteLongs: undefined, promoteValues: undefined, promoteBuffers: undefined, internalHint: null, collectionHint: null, name: 'test2', promiseLibrary: [Function: Promise], readConcern: undefined } } 

I assume that the Collection structure is a problem for my cycle, but I'm not sure what exactly is happening ... This is an example of the expected result for each collection:

 { _id: 5a13de85a55e615235f71528, b: 2 } 

Any help would be greatly appreciated! Thank you in advance!

+5
source share
2 answers

Although this is not the best syntax and useless except for the output of the log, this works for me:

 var mongodb = require('mongodb'); mongodb.connect('mongodb://localhost:27017/test', function (err, db) { if (err) { throw err; } db.listCollections().toArray(function (err, cols) { if (err) { throw err; } cols.forEach(function (col) { db.collection(col.name).find({}, {}, 0, 1, function (err, docs) { if(err){ throw err; } console.log(col); docs.forEach(console.log); }); }); }) }) 

So, perhaps the query conditions do not match anything?

Also better with Promises:

 const mongodb = require('mongodb'); const Promise = require('bluebird'); function getDb() { return Promise.resolve(mongodb.connect('mongodb://localhost:27017/test')); } function getCollections(db) { return Promise.resolve(db.listCollections().toArray()); } function getDocs(db, col) { return Promise.resolve(db.collection(col.name).find({},{},0,1).toArray()); } const data = {}; getDb() .then((db) => { data.db = db; return getCollections(db); }).then((cols) => { data.cols = cols; return Promise.map(cols, (col) => getDocs(data.db,col)); }).then((docs) => { console.log(docs); }) 
+1
source

The javaScript ForEach loop is synchronized until it contains an asynchronous call. In this case, you cannot call any DB call inside the loop.

Instead, you can use a library called async, which comes with some great features to solve this problem, as shown below.

 var MongoClient = require("mongodb").MongoClient, test = require("assert"), async = require('async'); MongoClient.connect("mongodb://localhost:27017/test", function (err, db) { db.listCollections().toArray(function (err, items) { test.ok(items.length >= 1); async.map(items, (each, callback) => { let collection = db.collection(each.name); collection.findOne({a: 2}, {fields: {b: 1}}, function (err, doc) { console.log(doc); callback(); }); }, (err) => { console.log("done"); }); }); db.close(); }); 
+1
source

Source: https://habr.com/ru/post/1273541/


All Articles