1

I'm building an API for my chat application and I wrote the endpoint below to save new messages in MongoDB.

The messages themselves are an array.

Testing this endpoint with Postman returns the newly created message in the response but the message is not added to my array of messages.

router.post('/:id/messages', async (request, response) => {
  const chatMessage = new Message({
    type: request.body.type,
    body: request.body.body,
    author: request.body.author
  });
  try {
    const newMessage = await chatMessage.save({ $push: { chatMessage } });
    response.status(201).json(newMessage);
  } catch (error) {
    response.status(400).json({ message: error.message });
  }
});

Here's my Mongoose schema for messages:

const mongoose = require('mongoose');

const messageSchema = new mongoose.Schema({
  type: {
    type: String
  },
  body: {
    type: String
  },
  author: {
    type: String
  },
  date: {
    type: Date,
    default: Date.now
  }
});

module.exports = mongoose.model('Message', messageSchema);

Any hints on what I've done wrong? Thank you so much! :-)

EDIT_ Mongo DB Sample

6
  • What does :id doing over there, Also are you inserting into Message collection or any other collection ? Plus where is the array in your schema ? Can you please give us sample of your docs from whatever collection you wanted to insert for better understanding.. Commented Dec 21, 2019 at 20:43
  • THanks for your question. I found out that my message is in fact posted to my DB. But this function opens a new collection - which i dont want. Every document in my DB has a messages document inside. this is where my message should go. So i thought defining the url to the messages would be specific enough. any more hints? Commented Dec 22, 2019 at 6:43
  • Can you please provide your sample documents, So Do you mean message :[] lies inside a document of some other collection ? (And message is an array of objects) ?? Every document in my DB has a messages document inside --> what do you mean by this ? DB will have collections & collections will have documents !! So in which collection do you want an array of objects called message as you don't want message collection then messages should got into a document of a collection !! Commented Dec 22, 2019 at 6:45
  • please see the picture at the end of my post. provided how my db looks Commented Dec 22, 2019 at 7:23
  • 1
    It should be based on _id in this case Commented Dec 22, 2019 at 7:28

3 Answers 3

1

Please make these changes :

chat schema file :

/** messages schema w.r.t. messages field in chat document */
const messageSchema = new mongoose.Schema({
    type: {
        type: String
    },
    body: {
        type: String
    },
    author: {
        type: String
    },
    date: {
        type: Date,
        default: Date.now
    }
});

/** Actual chat schema */
const chatsSchema = new mongoose.Schema({
    id: Number,
    user1: String,
    user2: String,
    messages: [messageSchema]
});

function getChatsModel() {
    if (mongoose.models && mongoose.models.chats) {
        return mongoose.models.chats;
    }
    return mongoose.model('chats', chatsSchema, 'chats');
}

module.exports = getChatsModel();

Code :

/** Import chats model file here & also do require mongoose */
router.post('/:id/messages', async (request, response) => {
    const chatMessage = {
        messages: {
            type: request.body.type,
            body: request.body.body,
            author: request.body.author
        }
    };
    try {
        const id = mongoose.Types.ObjectId(request.params.id);
        const dbResp = await Chats.findOneAndUpdate({ "_id": id }, { $push: chatMessage }, { new: true }).lean(true);
        if (dbResp) {
            // dbResp will be entire updated document, we're just returning newly added message which is input.
            response.status(201).json(chatMessage);
        } else {
            response.status(400).json({ message: 'Not able to update messages' });
        }
    } catch (error) {
        response.status(500).json({ message: error.message });
    }
});
Sign up to request clarification or add additional context in comments.

1 Comment

Amazing! Thank you so much for taking the time for my problem. Please have a great, great day :-)
0

According to mongodb documentation .save() is deprecated: https://docs.mongodb.com/manual/reference/method/db.collection.save/

You should try .update() command instead as shown in the $push example documentation: https://docs.mongodb.com/manual/reference/operator/update/push/

Comments

0

There's something with your schema and action that doesn't match.

You're using $push which is used to append data to an array. Your schema doesn't contain any array.

If your collection contains the messages as documents then you should use .insertOne instead.

router.post('/:id/messages', async (request, response) => {
  const chatMessage = {
    type: request.body.type,
    body: request.body.body,
    author: request.body.author
  }
  try {
    const newMessage = await chatMessage.insertOne(chatMessage);
    response.status(201).json(newMessage);
  } catch (error) {
    response.status(400).json({ message: error.message });
  }
})

newMessage would then contain the created document. Be aware that this code is untested.

1 Comment

Hey oliver. thanks for your help, but i get a chatMessage.insertOne is not a function

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.