0

Im new to mongoose and nosql databases. I have the following mongoose model (profile).

import { model, Schema } from 'mongoose';
import Joi from '@hapi/joi';

const profileSchema = new Schema({
  user: {
    type: Schema.Types.ObjectId,
    ref: 'users',
  },
  handle: {
    type: String,
    minlength: 2,
    maxlength: 20,
    required: true,
    trim: true,
  },
  company: {
    type: String,
    minlength: 1,
    maxlength: 100,
    trim: true,
  },
  website: {
    type: String,
    maxlength: 100,
    trim: true,
  },
  location: {
    type: String,
    maxlength: 100,
    trim: true,
  },
  status: {
    type: String,
    maxlength: 50,
    trim: true,
    required: true,
  },
  skills: {
    type: [String],
    required: true,
  },
  bio: {
    type: String,
    maxlength: 500,
    trim: true,
  },
  githubUserName: {
    type: String,
    maxlength: 50,
    trim: true,
  },
  socialLinks: {
    youtube: {
      type: String,
      maxlength: 100,
      trim: true,
    },
    twitter: {
      type: String,
      maxlength: 100,
      trim: true,
    },
    facebook: {
      type: String,
      maxlength: 100,
      trim: true,
    },
    linkedin: {
      type: String,
      maxlength: 100,
      trim: true,
    },
    instagram: {
      type: String,
      maxlength: 100,
      trim: true,
    },
  },
  date: {
    type: Date,
    default: Date.now,
  },
});

export default model('profile', profileSchema);

export const validateProfile = (profile) => {
  const schema = Joi.object({
    handle: Joi.string().trim().min(2).max(20).required(),
    company: Joi.string().trim().min(2).max(20),
    website: Joi.string().trim().max(100),
    location: Joi.string().trim().min(2).max(20),
    status: Joi.string().trim().min(2).max(20),
    skills: Joi.array().required(),
    bio: Joi.string().trim().max(500),
    githubUserName: Joi.string().max(50),
    youtube: Joi.string().trim().max(100),
    twitter: Joi.string().trim().max(100),
    facebook: Joi.string().trim().max(100),
    linkedin: Joi.string().trim().max(100),
    instagram: Joi.string().trim().max(100),
  });

  return schema.validate(profile);
};

Every profile can have several experiences. This is my experience model.

import { model, Schema } from 'mongoose';
import Joi from '@hapi/joi';

const experienceSchema = new Schema({
  title: {
    type: String,
    maxlength: 100,
    trim: true,
    required: true,
  },
  company: {
    type: String,
    maxlength: 100,
    trim: true,
    required: true,
  },
  location: {
    type: String,
    maxlength: 100,
    trim: true,
    required: true,
  },
  from: {
    type: Date,
    required: true,
  },
  to: {
    type: Date,
  },
  current: {
    type: Boolean,
    default: false,
  },
  description: {
    type: String,
    maxlength: 500,
    trim: true,
  },
});

export default model('experience', experienceSchema);

export const validateExperience = (profile) => {
  const schema = Joi.object({
    title: Joi.string().trim().max(100).required(),
    company: Joi.string().trim().max(100).required(),
    location: Joi.string().trim().max(100).required(),
    from: Joi.date().required(),
    to: Joi.date(),
    current: Joi.boolean().default(false),
    description: Joi.string().trim().max(500),
  });

  return schema.validate(profile);
}

;

I want to link this experience model to profile model. Experience is an array. So how can I link this experience model array to profile model? First I thought to keep the experience array inside the profile model, but it makes the model too big. I want to separate things here. What should be the better practice here??

Shashika Virajh
  • 8,497
  • 17
  • 59
  • 103

2 Answers2

1

you can add one field experience_ids in your Profile Schema , it will save ids of experience in Profile Schema

experience_ids: [{
    type: mongoose.Schema.Types.ObjectId,
    ref: 'experience'
  }]

you can populate experience like this :

Profile
 .find()
 .populate('experience_ids')
 .exec(...)
Saurabh Mistry
  • 12,833
  • 5
  • 50
  • 71
0

Nesting experience array inside the profile model wouldn't make the model 'too big'. Consider this any Person wont ideally have more than 20 companies that he had worked for in his entire career. In fact we would mostly be looking at a no less than 20 .Which in any case isn't a length that would slow the query.
Now as you have decided to not nest the experience inside the Profile array

what you can now do is to create an array that would hold the ids for experience and keep it in your Profile Schema

    experiences:[
        {
            type: mongoose.Schema.Types.ObjectId,
            ref: "experience"
        }
    ]
The ref keyword as you might have guessed is the name of the collection where the referenced document resides.

To retrieve the data for the user You would need to use

profile.findById(id).populate("experience").exec((err, User) =>{
 console.log(User);
});
the populate method basically is used for populating the data inside the reference while the execute method basically takes the query object returned but the Mongoose query and runs this as a unit to get your result read more about exec here : What does exec do ?
Nitin Khare
  • 147
  • 2
  • 10