2

I'm building a news website, and I this mongoose schema:

let mongoose = require('mongoose');

let articleSchema = mongoose.Schema({
  image1:{
    type: String,
    required: true
  },
  title:{
    type: String,
    required: true
  },
  author:{
    type: String,
    required: true
  },
  date:{
    type: String,
    required: true
  },
  updated:{
    type: String,
    default: 'not updated'
  },
  title_nd:{
    type: String,
    required: false
  },
  body:{
    type: String,
    required: true
  },
  comments: [commentsSchema],
  likes:{ type:Number, default:0 }
});

let Article = module.exports = mongoose.model('Article', articleSchema);

And I want to add a form so users can add their comments. The question is how do I create a new schema for comments and link it to article schema, and then if the user adds a comment the comment added to the database and then shows on the article comment section?

  • What do you have so far for your `commentsSchema` if anything? You can create a comments schema the same way you created the article schema just with different properties and obviously a different model name. In your comments schema you can add a property to your comments schema specifying an `ObjectId` which can tie back to the article. – Matt Croak Oct 17 '19 at 16:17

2 Answers2

5

Modeling a separate schema for comment is not a good idea in my humble opinion, since it is a classic case of one to few mapping which is an ideal use case for embedding the document. To give you a basic idea about data modeling i am quoting here

You need to consider two factors:

  • Will the entities on the ā€œNā€ side of the One-to-N ever need to stand alone?
  • What is the cardinality of the relationship: is it one-to-few; one-to-many; or one-to-squillions?

Based on these factors, you can pick one of the three basic One-to-N schema designs:

  • Embed the N side if the cardinality is one-to-few and there is no need to access the embedded object outside the context of the parent object
  • Use an array of references to the N-side objects if the cardinality is one-to-many or if the N-side objects should stand alone for any reasons
  • Use a reference to the One-side in the N-side objects if the cardinality is one-to-squillions

Please refer to a very well written and articulated post 6 Rules of Thumb for MongoDB Schema Design: Part 1 from mongodb blogs.

Even after this if you think it is a good idea to link to another schema please refer to this SO question - Referencing another schema in Mongoose

Jeet
  • 5,569
  • 8
  • 43
  • 75
0

so I found a solution for this:

// :id is all articles with all ids
router.post('/:id', function (req, res) {
  let comment = {};
  comment.body = req.body.body;
  comment.user = req.user;
  comment.date = new Date(Date.now()).toDateString();

  // Express validator
  req.checkBody('body').len(5, 100);

  let errors = [];
  errors = req.validationErrors();

  if(errors) {
    Article.findById(req.params.id, function (err, article) {
      if(err)throw err;
      req.flash('danger', 'Body minimum length is 5 and maximum 100!');
      res.redirect('/articles/'+article.id);
    });
  } else {
    Article.findById(req.params.id, function (err, article) {
      if(err)throw err;
     article.comments.push({'body':comment.body,'user':comment.user,'date':comment.date});
      article.save(function (err) {
        if (err) {
          throw err;
        }else {
          req.flash('success', 'Comment added!');
          res.redirect('/articles/'+article.id);
        }
      });
    });
  }
});

EDIT: code above in more readable form:

router.post('/:id', async (req, res) => {
  let article = await Article.findById(req.params.id);

  if (!article) res.status("403");

  let articleUrl = "/articles/${article.id}";

  let comment = {
    body: req.body.body,
    user: req.user,
    date: new Date(Date.now()).toDateString();
  };

  if (commment.body.lengh >= 100 || comment.body.length <= 5) {
    req.flash('danger', 'Body minimum length is 5 and maximum 100!');
    return res.redirect(articleUrl);
  }

  articles.comments.push(comment);

  await article.save();

  req.flash('success', 'Comment added!');
  res.redirect(articleUrl);

});