Basit
Basit

Reputation: 367

mongoose nested schemas for multiple array of objects

I am trying to build a rest api with node, express and mongodb for webapp where I have three routes or section on frontend

  1. Quotes
  2. Stories
  3. News

When user will click Quotes he will see only quotes, same will goes with Stories and News.

I am confused how to build schema for this kind of API.

This is my approach First I build separate schemas for each section then merge all of them in main ApiSchema... I am not sure if this approach is right

  const mongoose = require('mongoose')
  const Schema = mongoose.Schema

  const QuotesSchema = new Schema({
     author: {
        type: String,
        required: true
     },
     categories: {
        type: [String],
        required: true
     }
  })

  module.exports = Quotes = mongoose.model('quotes', QuotesSchema)

  const StoriesSchema = new Schema({
     title: {
        type: String,
        required: true
     },
     description: {
        type: String,
        required: true
     }
  })

  module.exports = Stories = mongoose.model('stories', StoriesSchema)

  const NewsSchema = new Schema({
     headline: {
        type: String,
        required: true
     }
     date: {
        type: Date,
        default: Date.now
     }
  })

 module.exports = News = mongoose.model('news', NewsSchema)

 const Quotes = require('./Quotes')
 const Stories = require('./Stories')
 const News = require('./News')

 const ApiSchema = new Schema({
     quotes: [Quotes],
     Stories: [Stories],
     News: [News]
  })


  module.exports = Api = mongoose.model('api', ApiSchema)

I want my api like below example

  [
     {
        quotes: [
           { author: 'John', quote: 'be happy', tags: ['life', 'heart'] },
           { author: 'Mark', quote: 'be creative', tags: ['motivation', 'education'] }
        ]
     },
     {
        story: [
           { title: 'broken heart', description: 'sit ae Ipsa, laboriosam!', category: ['lorem1', 'lorem2'] },
           { title: 'lorem ipsum', description: 'Lorem ipsum dolor sit.', category: ['lorem1', 'lorem2'] }
        ]
     },
     {
        news: [
           { headline: 'ipsum Lorem', city: 'Jehigi' },
           { headline: 'Lorem, ipsum', city: 'Fahmori' }
        ]
     }
  ]

I hope I am clear. will so kind of you if you help me out.

Upvotes: 4

Views: 3080

Answers (1)

ajbieber
ajbieber

Reputation: 729

I think you are on the right track, but you should be using references instead.

(1) Having four separate models and four separate schemas is a good idea, but I'd ensure they are separated into separate files.

(2) In your APISchema, you can reference each of the other schemas, like this:

const ApiSchema = new Schema({
  quotes: [{ type: mongoose.Schema.Types.ObjectId,, ref: 'quotes' }]
  stories: [{ type: mongoose.Schema.Types.ObjectId,, ref: 'stories' }],
  news: [{ type: mongoose.Schema.Types.ObjectId,, ref: 'news' }]
});

(3) Now when you create an API document, you must have the _id of the quotes, stories, and news at hand. If you do, its very simple from there

const quotes = []; // Array of quote _ids
const stories = []; // Array of story _ids
const news = []; // Array of news _ids

const apiObject = {
  quotes: quotes,
  stories: stories,
  news: news
};

// Save the API Object to the database
apiObject.save()
.then((savedObject) => {
  // Here is your saved object. Database should be accurate.
});

The benefit to doing it this way is population. When you go to find the API document from the database, you can populate each of these fields and return the entire object

API.find({}).populate('quotes stories news')
.then((apiObjects) => {
// Populated documents
});

Additionally, when you want/need to update a quote lets say, its much simpler to update the quote through its own model, calling Quote.update(), rather than trying to update it though the API model

Upvotes: 2

Related Questions