Search code examples
mongoose

dropCollection not working. Still see collections


The following code should drop all connections but I see that subsequent call to collections returns collections which should be empty. What am I doing wrong?

const collectionsBeforeDrop = await db.collections();
    collectionsBeforeDrop.forEach(async (c) => {
      console.log(`got collection name : ${c.collectionName}`);
      await db.dropCollection(c);
    });
    console.log(`checking after cleanup`)
    const collectionsAfterDrop = await db.collections();
    collectionsAfterDrop.forEach(c => {
      console.log(`got collection name after claanup! THIS SHOULDN'T HAVE HAPPENED : ${util.inspect(c.collectionName)}`); //THIS CODE HITS
      throw new Error("couldn't clean up after test case");
    });

Output

cleaning up                                                                                                                

      at Object.log (test/question.test.js:61:13)

  console.log                                                                                                                  
    got db [object Object]                                                                                                     

      at Object.log (test/question.test.js:64:13)

  console.log                                                                                                                  
    truncating collections of db Questions                                                                                     

      at Object.log (test/question.test.js:67:13)

  console.log
    got collection name : areas

      at log (test/question.test.js:72:15)
          at Array.forEach (<anonymous>)

  console.log                                                                                                                  
    checking after cleanup                                                                                                     

      at Object.log (test/question.test.js:75:13)

  console.log                                                                                                                  
    got collection name after claanup! THIS SHOULDN'T HAVE HAPPENED : 'areas'

      at log (test/question.test.js:78:15)
          at Array.forEach (<anonymous>)

Solution

  • You shouldn't be using async within a forEach loop, because forEach do not wait for the await.

    So what happens is that your forEach loop fires multiple async calls to drop the collections, and then immediately goes to collectionsAfterDrop. So at this time, the collections are not yet dropped.

    So to fix your issue, you can change your code to:

    const collectionsBeforeDrop = await db.collections();
    
    for (const collection of collectionsBeforeDrop) {
      console.log(`got collection name : ${c.collectionName}`);
      await db.dropCollection(c);
    }
    
    // will reach here only after all collections are removed
    
    console.log(`checking after cleanup`)
    
    const collectionsAfterDrop = await db.collections();
    
    for (const collection of collectionsAfterDrop) {
      console.log(`got collection name after claanup! THIS SHOULDN'T HAVE HAPPENED : ${util.inspect(c.collectionName)}`); //THIS CODE HITS
      throw new Error("couldn't clean up after test case");
    }