0

I am trying to create a script that will populate my Mongo database using data returned from a few API calls. Ideally, this would be run manually every once in a while or on a scheduler to update the database with fresh data, so I am trying to do everything inside of the 'MongoClient.conncect' function. I would like to import this data one API call at a time and am trying to avoid the ugliness of chained promises and .then's. I have done some research on using async/await and it seems to me that using the 'await' keyword is effectively unwrapping the returned promise. If that is the case, I can't quite figure out why it is not waiting properly. Here is what I have so far:

const MongoClient = require('mongodb').MongoClient;
const fs = require('fs');
const assert = require('assert');
const ProPublicaAPI = require('./ProPublicaAPI');
var constants = require('../common/constants');
var https = require('https');

const url = 'mongodb://localhost:27017';


dbName = 'government';

MongoClient.connect(url, function(err, client) {
  assert.equal(null, err);
  console.log('successfully connected to mongoDB server: ' + url);

  const db = client.db(dbName);
  try{
    var senateInsert = waitInsert(db, 'senate');
  }
  catch(err) {
    console.log(err);
  }
  console.log('closing database connection');
  client.close();
})

async function waitInsert(db, collection) {
  //I made this function just to call inside the MongoClient.connect() above
  return await insertSenateDocuments(db, collection);
}

function insertSenateDocuments(db, chamber) {
  return new Promise(function(resolve) {
    var collection = db.collection(chamber);
    //method that calls API, to be converted into async/await later
    senateMembers = ProPublicaAPI.getAllMembersByChamber(chamber);
    senateMembers.then(function(promisedMembers) {
      console.log("Recieved data from api");
      collection.insertMany(promisedMembers, function(err, result) {
        if(err) return console.log(err);
        console.log(`Imported ${chamber} data`);
        resolve(result);
      });
    })
  })
}

And here is the stack trace:

successfully connected to mongoDB server: mongodb://localhost:27017
about to close
Recieved collection Data
{ MongoError: server instance pool was destroyed
    at basicWriteValidations (D:\Dev\node\node_modules\mongodb-core\lib\topologies\server.js:636:41)
    at Server.insert (D:\Dev\node\node_modules\mongodb-core\lib\topologies\server.js:737:16)
    at Server.insert (D:\Dev\node\node_modules\mongodb\lib\topologies\topology_base.js:315:25)
    at executeCommands (D:\Dev\node\node_modules\mongodb\lib\bulk\ordered.js:525:23)
    at executeOperation (D:\Dev\node\node_modules\mongodb\lib\utils.js:408:22)
    at OrderedBulkOperation.execute (D:\Dev\node\node_modules\mongodb\lib\bulk\ordered.js:602:10)

    at bulkWrite (D:\Dev\node\node_modules\mongodb\lib\collection.js:627:8)
    at executeOperation (D:\Dev\node\node_modules\mongodb\lib\utils.js:408:22)
    at Collection.insertMany (D:\Dev\node\node_modules\mongodb\lib\collection.js:512:10)
    at D:\Dev\node\dataimporter\mongo.js:39:18
  name: 'MongoError',
  message: 'server instance pool was destroyed' }
PS D:\Dev\node\dataimporter> node mongo
successfully connected to mongoDB server: mongodb://localhost:27017
closing database connection
Recieved data from api
{ MongoError: server instance pool was destroyed
    at basicWriteValidations (D:\Dev\node\node_modules\mongodb-core\lib\topologies\server.js:636:41)
    at Server.insert (D:\Dev\node\node_modules\mongodb-core\lib\topologies\server.js:737:16)
    at Server.insert (D:\Dev\node\node_modules\mongodb\lib\topologies\topology_base.js:315:25)
    at executeCommands (D:\Dev\node\node_modules\mongodb\lib\bulk\ordered.js:525:23)
    at executeOperation (D:\Dev\node\node_modules\mongodb\lib\utils.js:408:22)
    at OrderedBulkOperation.execute (D:\Dev\node\node_modules\mongodb\lib\bulk\ordered.js:602:10)
    at bulkWrite (D:\Dev\node\node_modules\mongodb\lib\collection.js:627:8)
    at executeOperation (D:\Dev\node\node_modules\mongodb\lib\utils.js:408:22)
    at Collection.insertMany (D:\Dev\node\node_modules\mongodb\lib\collection.js:512:10)
    at D:\Dev\node\dataimporter\mongo.js:39:18
  name: 'MongoError',
  message: 'server instance pool was destroyed' }

As you can see, the client.close() is being called before the inserting of the documents is taking place.

3
  • var senateInsert = waitInsert(db, 'senate'); this line does not wait for your async calls. you have to declare it. you may consider doing connect in a function too Commented Feb 7, 2018 at 8:31
  • could you please try var senateInsert = await waitInsert(db, 'senate'); instead var senateInsert = waitInsert(db, 'senate'); and let me know the result Commented Feb 7, 2018 at 8:31
  • Thank you, I will try this. However, I am curious, if await is 'unwrapping' the Promise and I am returning it in waitInsert, why then do I have to call await again when I call waitInsert? Is there a way to do this without having to use waitInsert at all and just directly call insertSenateDocuments? Commented Feb 7, 2018 at 17:19

2 Answers 2

3

You have to await for waitInsert

MongoClient.connect(url, async function(err, client) {
  assert.equal(null, err);
  console.log('successfully connected to mongoDB server: ' + url);

  const db = client.db(dbName);
  try{
    var senateInsert = await waitInsert(db, 'senate');
  }
  catch(err) {
    console.log(err);
  }
  console.log('closing database connection');
  client.close();
})
Sign up to request clarification or add additional context in comments.

Comments

0

Easier:

bulkWriteItems(array, collection) {
    return collection.bulkWrite(array, {ordered: true, w: 1})
}

Call:

async saveData() {
    let bulk = [];
    for (let i = 0; i < 100; i++) {
        let name = `item${i}`
        bulk.push({insertOne: {name}});
    }
    return db.collection(COLLECTION_OBJECTS).then(collection => this.bulkWriteItems(bulk, collection))
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.