Home > Software engineering >  Issue Trying to Save an Array of Object Ids Mongoose
Issue Trying to Save an Array of Object Ids Mongoose

Time:12-11

I am using mongoose and express to create my database and server respectively.

I have a Schema like below for my data:

const mongoose = require('mongoose')
const {Schema} = mongoose

const quotesSchema = new Schema({
  tags: [
    {
        type: mongoose.Schema.Types.ObjectId,
        ref: 'Tags' // I want to save an array of tags coming in from the request body
     }
   ],
  content: {
     type: String,
     required: true
  },
  author: {
     type: String,
     required: true
  },
  authorSlug: {
     type: String,
  },
  dateAdded: {
     type: Date,
     default: Date.now()
  },
   dateModified: {
      type: Date,
      default: Date.now()
   },
})

const Quotes = new mongoose.model('Quotes', quotesSchema)
module.exports = Quotes

I want to save an array of tags coming in from the request body but it only saves one item from the array.

Here's my sample code:

router.post('/', async (req, res, next) => {
try {
    const {tags, author, content} = req.body
    const slug = author.replace(/\s /g, '-').toLowerCase()

    var tagIds = []
    
    tags.forEach( async (tag) => {
        const foundTag = await Tag.find({name: tag}) // I first of all search my tag collection 
 // to see if the names supplied in the request body tags array exist, 
 // then try to extract their Objectids and store in an array to move to the next step - saving the quote

        // foundTag.forEach(async (item) => {
        //     return await tagIds.push(item._id)
        // })            

        for (var i = 0; i < foundTag.length; i  ) {
            tagIds.push[i]
        }

        console.log(tagIds)
        
        const quote = new Quote({
            tags: tagIds,
            content,
            author,
            authorSlug: slug
        })

        const quoteToSave = await quote.save()

        return res.status(201).json({
            success: true,
            msg: 'Quote Created Successfully',
            quote: quoteToSave
        })

     })
  } catch (error) {
     console.error(error)
  }
})

How do I pass the complete array of tags as a parameter to my quote to save. I think the issue here is that it doesn't wait for the second tag to enter the array.

Here's an image of my request-response in Postman:

image description

How do I get the tags which is an array from req.body and save it as part of my quote object? At the moment I am doing everything inside my forEach loop and it doesn't seem decent enough to me. Is there a best approach like wait for the data then the save part will not have any parent control statement, like currently.

Thanks

CodePudding user response:

#1 If you will use async functions inside forEach then use Promise.all() with bluebird.

#2 MongoDB operators are very useful.

#3 Knowing the difference between forEach and map is very important.

#4 express response doesn't need return statement if you use it correctly.


The final code will look something like:

router.post('/', async (req, res, next) => {

    const { tags, author, content } = req.body
    const slug = author.replace(/\s /g, '-').toLowerCase()

    var foundTags = await Tag.find({ name: { $in: tags } })

    if (foundTags) {

        var tagsIds = []
        foundTags.map(tag => {
            tagsIds.push(tag._id);
        })

        const quote = new Quote({
            tags: tagsIds,
            content,
            author,
            authorSlug: slug
        })

        const quoteToSave = await quote.save()

        if (quoteToSave) {
            res.status(201).json({
                success: true,
                msg: 'Quote Created Successfully',
                quote: quoteToSave
            })
        } else {
            res.status(500).json("failed saving quote")
        }
    } else {
        res.status(500).json("failed finding tags")
    }
})
  • Related