0

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

1 Answer 1

1

#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")
    }
})
Sign up to request clarification or add additional context in comments.

5 Comments

Bro, this works perfectly. Can you explain the usecase of that in operator? It seems to do wonders for me, so I can adopt it. Also, tags and quote are tied together. I want a scenario where if I create a quote with a tag name, that tag will update it's quote count. Shall I share a snippet? Thanks
Glad it worked, MongoDB operators are well documented and also there are good amount of articles, comparisons and usecases about them.
I'm open to help with you in that scenario, but after you try to solve it then if you got stuck and couldn't find any previous question here, I will try to help with you.
Thanks. Have been reading up on operators.
Let me give it another shot. I'll most likely ask another question and share the link here. That works?

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.