Search code examples
mongodbmongoose

Not able to add document in right collection in Mongodb


I am running a test case which should add a document in areas collection in Questions database in mongo using mongoose.

I am facing two problems though. Why?

  1. The document gets created in test database instead of Questions.

This function does most of the heavy lifting

async function addQuestion (description,hints,topic) {
  var q = null;
  console.log(`adding question:`);
  console.log(`description: ${description}`);
  console.log(`hints: ${hints}`);
  console.log(`topic: ${topic}`);
  var db = mongoUtils.dbclass.getDb();
  console.log(`addQuestion: db is ${util.inspect(db)}`);
  console.log(`looking for collection for topic: ${topic}`);
  const topicSpecificCollection = await db.collection(topic);
  console.log(`got collection  ${util.inspect(topicSpecificCollection)}`);

  /*in the mongoose.model call below, the first argument is the singular name of the collection the model is for.
   Mongoose automatically looks for the plural, lowercased version of your model name. 
   The model `area` is for the `areas` collection in the database. */
  const Question = mongoose.model(topic, questionSchema); //I ASSUME THAT IF TOPIC IS `area` THEN MONGOOSE WILL ADD THE DOCUMENT IN `areas` COLLECTION
  q = Question({
      description: description,
      hints: hints,
      topic: topic
  });
  await q.save()
  .then ((result) => {
    console.log(`added question ${result}`);
    return result;
  })
  .catch ( (err)=>{
    console.log(`error in adding question: ${err}`);
    return null;
  });
}

The schema is

const mongoose = require("mongoose");

const questionSchema = new mongoose.Schema({
    description: String,
    hints: [String],
    topic: String
}); 


module.exports = questionSchema;
  1. The second issue is that while I am returning result above, the calling function gets undefined. See traces below.

The test is

  it("should add a question about calculating area in Area collection", async ()=>{

    const topic = "area"; //THIS SHOULD BE ADDED IN `areas` COLLECTION?
    const description = "description of question on area";
    const hints = ["area hint 1", "area hint 2"];
    
    req = {
      "description": description,
      "hints" : hints,
      "topic" :topic
    }

    res = {

    }
  
    const Question = mongoose.model(topic, questionSchema);
    q = Question({
        description: description,
        hints: hints,
        topic: topic
      });

    const expectedResponse = {'questionAdded': req}

    await questionControllerModule.addQuestionHandler(req,res)
    .then((result) => {
        console.log(`added question ${result}`); //TRACES SHOW THAT result IS undefined
        expect(result).toBe(q);
      })
  });

The output is

console.log                                                                                                                        
    adding question:                                                                                                                 

      at log (controllers/question.js:11:11)

  console.log                                                                                                                        
    description: description of question on area                                                                                     

      at log (controllers/question.js:12:11)

  console.log                                                                                                                        
    hints: area hint 1,area hint 2

      at log (controllers/question.js:13:11)

  console.log                                                                                                                        
    topic: area                                                                                                                      

      at log (controllers/question.js:14:11)

  console.log                                                                                                                        
    addQuestion: db is Db {                                                                                                          
      s: {
        options: {
          enableUtf8Validation: true,
          forceServerObjectId: false,
          pkFactory: [Object],
          raw: false,
          readPreference: [ReadPreference],
          retryWrites: true
        },
        readPreference: ReadPreference {
          mode: 'primary',
          tags: undefined,
          hedge: undefined,
          maxStalenessSeconds: undefined,
          minWireVersion: undefined
        },
        bsonOptions: {
          raw: false,
          useBigInt64: false,
          promoteLongs: true,
          promoteValues: true,
          promoteBuffers: false,
          ignoreUndefined: false,
          bsonRegExp: false,
          serializeFunctions: false,
          fieldsAsRaw: {},
          enableUtf8Validation: true
        },
        pkFactory: { createPk: [Function: createPk] },
        readConcern: undefined,
        writeConcern: undefined,
        **namespace: MongoDBNamespace { db: 'Questions', collection: undefined }** //DON'T KNOW WHY collection IS undefined.
      },
      client: <ref *1> MongoClient {
        _events: [Object: null prototype] {
          serverDescriptionChanged: [Function (anonymous)]
        },
        _eventsCount: 1,
        _maxListeners: 0,
        mongoLogger: MongoLogger {
          error: [Function: bound log],
          warn: [Function: bound log],
          info: [Function: bound log],
          debug: [Function: bound log],
          trace: [Function: bound log],
          componentSeverities: [Object],
          maxDocumentLength: 1000,
          logDestination: [Object]
        },
        s: {
          url: 'mongodb://0.0.0.0:27017/',
          bsonOptions: [Object],
          namespace: [MongoDBNamespace],
          hasBeenClosed: false,
          sessionPool: [ServerSessionPool],
          activeSessions: [Set],
          options: [Getter],
          readConcern: [Getter],
          writeConcern: [Getter],
          readPreference: [Getter],
          isMongoClient: [Getter]
        },
        topology: Topology {
          _events: [Object: null prototype],
          _eventsCount: 26,
          _maxListeners: undefined,
          client: [Circular *1],
          selectServerAsync: [Function (anonymous)],
          s: [Object],
          [Symbol(kCapture)]: false,
          [Symbol(waitQueue)]: [List]
        },
        connectionLock: undefined,
        [Symbol(kCapture)]: false,
        [Symbol(options)]: [Object: null prototype] {
          hosts: [Array],
          compressors: [Array],
          connectTimeoutMS: 30000,
          directConnection: false,
          driverInfo: [Object],
          enableUtf8Validation: true,
          forceServerObjectId: false,
          heartbeatFrequencyMS: 10000,
          keepAlive: true,
          keepAliveInitialDelay: 120000,
          loadBalanced: false,
          localThresholdMS: 15,
          maxConnecting: 2,
          maxIdleTimeMS: 0,
          maxPoolSize: 100,
          minPoolSize: 0,
          minHeartbeatFrequencyMS: 500,
          monitorCommands: false,
          noDelay: true,
          pkFactory: [Object],
          raw: false,
          readPreference: [ReadPreference],
          retryReads: true,
          retryWrites: true,
          serverSelectionTimeoutMS: 30000,
          socketTimeoutMS: 0,
          srvMaxHosts: 0,
          srvServiceName: 'mongodb',
          waitQueueTimeoutMS: 0,
          zlibCompressionLevel: 0,
          dbName: 'test',
          userSpecifiedAuthSource: false,
          userSpecifiedReplicaSet: false,
          mongoLoggerOptions: [Object],
          metadata: [Object],
          [Symbol(@@mdb.enableMongoLogger)]: false
        }
      }
    }

      at log (controllers/question.js:17:11)

  console.log                                                                                                                        
    looking for collection for topic: area                                                                                           

      at log (controllers/question.js:18:11)

  console.log                                                                                                                        
    got collection  Collection {                                                                                                     
      s: {
        db: Db { s: [Object], client: [MongoClient] },
        options: {
          raw: false,
          useBigInt64: false,
          promoteLongs: true,
          promoteValues: true,
          promoteBuffers: false,
          ignoreUndefined: false,
          bsonRegExp: false,
          serializeFunctions: false,
          fieldsAsRaw: {},
          enableUtf8Validation: true,
          readPreference: [ReadPreference]
        },
        **namespace: MongoDBCollectionNamespace { db: 'Questions', collection: 'area' },** //HERE I SEE THE COLLECTION area THOUGH
        pkFactory: { createPk: [Function: createPk] },
        readPreference: ReadPreference {
          mode: 'primary',
          tags: undefined,
          hedge: undefined,
          maxStalenessSeconds: undefined,
          minWireVersion: undefined
        },
        bsonOptions: {
          raw: false,
          useBigInt64: false,
          promoteLongs: true,
          promoteValues: true,
          promoteBuffers: false,
          ignoreUndefined: false,
          bsonRegExp: false,
          serializeFunctions: false,
          fieldsAsRaw: {},
          enableUtf8Validation: true
        },
        readConcern: undefined,
        writeConcern: undefined
      },
      client: <ref *1> MongoClient {
        _events: [Object: null prototype] {
          serverDescriptionChanged: [Function (anonymous)]
        },
        _eventsCount: 1,
        _maxListeners: 0,
        mongoLogger: MongoLogger {
          error: [Function: bound log],
          warn: [Function: bound log],
          info: [Function: bound log],
          debug: [Function: bound log],
          trace: [Function: bound log],
          componentSeverities: [Object],
          maxDocumentLength: 1000,
          logDestination: [Object]
        },
        s: {
          url: 'mongodb://0.0.0.0:27017/',
          bsonOptions: [Object],
          namespace: [MongoDBNamespace],
          hasBeenClosed: false,
          sessionPool: [ServerSessionPool],
          activeSessions: [Set],
          options: [Getter],
          readConcern: [Getter],
          writeConcern: [Getter],
          readPreference: [Getter],
          isMongoClient: [Getter]
        },
        topology: Topology {
          _events: [Object: null prototype],
          _eventsCount: 26,
          _maxListeners: undefined,
          client: [Circular *1],
          selectServerAsync: [Function (anonymous)],
          s: [Object],
          [Symbol(kCapture)]: false,
          [Symbol(waitQueue)]: [List]
        },
        connectionLock: undefined,
        [Symbol(kCapture)]: false,
        [Symbol(options)]: [Object: null prototype] {
          hosts: [Array],
          compressors: [Array],
          connectTimeoutMS: 30000,
          directConnection: false,
          driverInfo: [Object],
          enableUtf8Validation: true,
          forceServerObjectId: false,
          heartbeatFrequencyMS: 10000,
          keepAlive: true,
          keepAliveInitialDelay: 120000,
          loadBalanced: false,
          localThresholdMS: 15,
          maxConnecting: 2,
          maxIdleTimeMS: 0,
          maxPoolSize: 100,
          minPoolSize: 0,
          minHeartbeatFrequencyMS: 500,
          monitorCommands: false,
          noDelay: true,
          pkFactory: [Object],
          raw: false,
          readPreference: [ReadPreference],
          retryReads: true,
          retryWrites: true,
          serverSelectionTimeoutMS: 30000,
          socketTimeoutMS: 0,
          srvMaxHosts: 0,
          srvServiceName: 'mongodb',
          waitQueueTimeoutMS: 0,
          zlibCompressionLevel: 0,
          dbName: 'test',
          userSpecifiedAuthSource: false,
          userSpecifiedReplicaSet: false,
          mongoLoggerOptions: [Object],
          metadata: [Object],
          [Symbol(@@mdb.enableMongoLogger)]: false
        }
      }
    }

      at log (controllers/question.js:20:11)

  console.log //THIS PROBABLY IS BECAUSE THE QUESTION GOT ADDED IN TEST DATABASE
    added question {
      description: 'description of question on area',
      hints: [ 'area hint 1', 'area hint 2' ],
      topic: 'area',
      _id: new ObjectId("64f380a9df8906232c783779"),
      __v: 0
    }

      at log (controllers/question.js:33:13)

  console.log                                                                                                                        
    **added question undefined** //BUT THE CALLIG FUNCTION GETS UNDEFINED RETURN VALUE                                                                                                        

      at log (controllers/question.js:71:13)

  console.log                                                                                                                        
    added question undefined                                                                                                         

      at log (test/question.test.js:49:17)

  console.log
    closing database connection

      at Object.log (test/question.test.js:15:11)

 FAIL  test/question.test.js
  Operations to manage questions should work
    × should add a question about calculating area in Area collection (152 ms)                                                       
                                                                                                                                     
  ● Operations to manage questions should work › should add a question about calculating area in Area collection                     
                                                                                                                                     
    expect(received).toBe(expected) // Object.is equality

    Expected: {"_id": "64f380a9df8906232c783778", "description": "description of question on area", "hints": ["area hint 1", "area hint 2"], "topic": "area"}
    Received: undefined

      48 |     .then((result) => {
      49 |         console.log(`added question ${result}`);
    > 50 |         expect(result).toBe(q);
         |                        ^
      51 |       })
      52 |   });
      53 | });

      at toBe (test/question.test.js:50:24)
      at Object.<anonymous> (test/question.test.js:47:5)

The result in MongoCompass

enter image description here

Code to connect to database

dbConnectMongoose: async function (){

          console.log(`trying to connect to uri ${process.env.DATABASE_URL}`);
          const connection = await mongoose.connect(process.env.DATABASE_URL); //DATABASE_URL=mongodb://0.0.0.0:27017
          console.log(`connected to Mongo.`);
          var localdbClient = connection.connections[0].client;
          var localdb;
          console.log(`got MongoClient: `); //for circular objects, JSON.stringify doesn't work
          try {
            localdb = localdbClient.db(process.env.DATABASE);
            console.log(`connected to database ${localdb.databaseName}`);
            const collections = await localdb.collections();
            collections.forEach(c => {console.log(`got collection ${c.collectionName}`)})
          } catch(exception) {
            console.log(`something bad happened in dbconnect: ${exception}`);
          } finally {
            this.db  = localdb;
            this.dbClient  = localdbClient;
            this.dbConnection = connection;
            console.log(`db Class db is ${this.db}`);
            console.log(`db Class dbClient is ${this.dbClient}`);
            console.log(`db Class dbConnection is ${this.dbConnection}`);
            }
        }

Solution

  • You need to specify the database name in the connection url, like this:

    DATABASE_URL=mongodb://0.0.0.0:27017/questions
    

    By default, if omitted it connects to the test database.

    For your second problem, you are mixing async-await, with Promise methods. You should do either this:

    return q.save()
      .then ((result) => {
        console.log(`added question ${result}`);
        return result;
      })
      .catch ( (err)=>{
        console.log(`error in adding question: ${err}`);
        return null;
      });
    

    Or try this:

    try {
        const result = await q.save();
        console.log(`added question ${result}`);
        return result;
    } catch(err){
        console.log(`error in adding question: ${err}`);
        return null;
    };
    

    Update this behavior in all of your functions.