Search code examples
node.jsmongodbmongoosereal-timepusher

How to make watch() function work in mongoDB?


I am trying to build a Chat-App using Pusher for realtime communication with the help of MongoDB. These are my files.

dbMessages.js

    import mongoose from 'mongoose'
    
    const pinguSchema = mongoose.Schema({
        message: String,
        name: String,
        timestamp: String,
        received: Boolean
    })
    
    export default mongoose.model('messagecontents', pinguSchema)

server.js

import express from "express"
import mongoose from 'mongoose'
import Messages from './dbMessages.js'
import Pusher from 'pusher'

//config
const app = express()
const port = process.env.PORT || 9000

const pusher = new Pusher({
    appId: "###",
    key: "###",
    secret: "###",
    cluster: "###",
    useTLS: ###
  });


//middleware
app.use(express.json())

//DB config
const connection_url = "###";

mongoose.connect(connection_url,{
    useCreateIndex: true,
    useNewUrlParser: true,
    useUnifiedTopology: true
})

const db = mongoose.connection;

db.once("open", () => {
    console.log("DB connected...")
})

const msgCollection = db.collection("messagecontents");
const changeStream = msgCollection.watch();

changeStream.on("change", (change)=>{
    console.log(change);

    
//api routes
app.get('/', (req,res) => {
    res.status(200).send('hello')
})


app.get('/messages/sync', (req,res) => {
    Messages.find((err, data) => {
        if(err){
            res.status(500).send(err)
        } else{
            res.status(200).send(data)
        }
    })
})


app.post('/messages/new', (req,res) => {
    const dbMessage = req.body

    Messages.create(dbMessage, (err, data) => {
        if(err){
            res.status(500).send(err)
        } else{
            res.status(201).send(data)
        }
    })
})


//listen
app.listen(port, () => console.log(` Server running on port: ${port}`))

What i am trying to get is the 'change' in my console, By the API http://localhost:9000/messages/new But The Error that I am getting is

[nodemon] 2.0.4 [nodemon] to restart at any time, enter rs [nodemon] watching path(s): . [nodemon] watching extensions: js,mjs,json
[nodemon] starting node server.js C:\Users\Desktop\Pingu - Chat App\backend\node_modules\mongoose\lib\drivers\node-mongodb-native\collection.js:145 throw new Error('Collection method ' + i + ' is synchronous'); ^

Error: Collection method watch is synchronous at NativeCollection. [as watch] (C:\Users\Desktop\Pingu - Chat App\backend\node_modules\mongoose\lib\drivers\node-mongodb-native\collection.js:145:15) at file:///C:/Users/Desktop/Pingu%20-%20Chat%20App/backend/server.js:38:36 at ModuleJob.run (internal/modules/esm/module_job.js:146:23) at async Loader.import (internal/modules/esm/loader.js:165:24) at async Object.loadESM (internal/process/esm_loader.js:68:5) [nodemon] app crashed - waiting for file changes before starting...

Here is the link to the documentation docs.mongodb.com/manual/changeStreams from here what I can get is that it can be done in two ways I implemented the 'watch' way, but don't know how to implement the async-await way.

Also here is the link to the youtube video from where I was trying to learn, youtube.com/watch?v=gzdQDxzW2Tw this part start from the time-stamp 2:59:00

Can anyone Help? Thanks in Advance.


Solution

  • I'm sorry that the comments that you got were completely unhelpful and a waste of time. All of the code that you shared is actually helpful in terms of fixing the problem.

    The issue is that you are calling the watch function without ensuring that you have a connection to the database. Connecting to mongo is async, so when you call watch function, you might still be in the process of making a a db connection. Modify your code like so...

    const db = mongoose.connection;
    
    db.once("open", () => {
        console.log("DB connected...");
    const msgCollection = db.collection("messagecontents");
    const changeStream = msgCollection.watch();
    
    changeStream.on("change", (change) => 
        console.log(change);
    );
    })
    
    

    I hope that helps. I am very disappointed in the other comments received.