Create embeded docs mongoose - node.js

I've the following mongoose schema:
'use strict';
const PostSchema = new Schema({
description: require('../fields/description'),
image: require('../fields/image'),
createdAt: require('../fields/createdAt'),
location: Location,
owner: require('../fields/owner') }, {
toObject: {
virtuals: true,
getters: true,
setters: true
},
toJSON: {
virtuals: true,
getters: true,
setters: true
} });
module.exports = mongoose.model('Post', PostSchema);
LocationSchema.js
'use strict';
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const LocationSchema = new Schema({
description: {
type: String,
required: true
},
point:{
type: [Number],
index: '2d',
required: true
},
createdAt:{
type: Date,
required: true,
default: new Date()
}
});
module.exports = mongoose.model('Location', LocationSchema);
and when i will restart my nodejs server i've the following error message:
TypeError: Undefined type Model at location Did you try nesting
Schemas? You can only nest using refs or arrays.
Someone know how to solve this ?

your error here represents that you have not given reference to location key in your post collection if you want to give location id to your post collection you have to provide reference to your collection.
example:
var PostSchema = new mongoose.Schema({
location: [{ type: mongoose.Schema.Types.ObjectId, ref: 'location' }]
});

Related

How to register a post model post within the model category in mongoDB?

Example:
I created two models, a "post" model and a "category" model.
I would like to create a category and when I create the post, I reference the id of the category and automatically register this post within "PostsId" in the category model. I don't think I did it correctly.
post model
const mongoose = require('mongoose');
const PostSchema = new mongoose.Schema(
{
title: {
type: String,
required: true,
},
img: {
type: String,
required: false,
},
desc: {
type: String,
required: true,
},
category: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Category',
required: true,
},
createdAt: {
type: Date,
default: Date.now,
}
},
{ timestamps: true }
);
module.exports = mongoose.model('Post', PostSchema);
category model
const mongoose = require('mongoose');
const CategorySchema = new mongoose.Schema(
{
name: {
type: String,
required: true,
},
postsId: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Post',
default: null,
}
},
{ timestamps: true }
);
module.exports = mongoose.model('Category', CategorySchema);

mongoose population (refs) is not working

I have created two models where I am trying to ref one model to another but it's not working and I don't have any idea about it I used it exactly the same way as in the mongoose example but it is not helping, the only difference between my working and their example is I have two different files for both models and I am exporting them to use in another file
The example I took reference from Mongoose
First Model
const userModel = require('./userModel')
const {Schema} = mongoose
const tweet = new Schema({
date: {
type: Date,
required: true,
},
msg:{
type: String,
maxlength:140,
required:true
},
tweetid:{
type: mongoose.Types.ObjectId
}
})
const tweetSchema = new Schema({
user: {
type: Schema.Types.ObjectId,
ref: 'userModel'
},
tweets: {
type: [{tweet}],
default: []
}
})
const tweetModel = mongoose.model('tweet',tweetSchema)
module.exports = tweetModel
Second Model
const {Schema} = mongoose
const userSchema = new Schema({
email: {
type:String,
required: true,
unique: true,
trim:true
},
password: {
type:String,
required: true,
trim:true
},
follows: {
type: [String],
default: []
}
})
const userModel = mongoose.model("User",userSchema)
module.exports = userModel
Your reference string should be equal to the model name that you have passed to mongoose.model:
const tweetSchema = new Schema({
user: {
type: Schema.Types.ObjectId,
ref: 'User'
},
tweets: {
type: [{tweet}],
default: []
}
})

Why can't I use '0' as an _id with mongoDB and mongoose?

I have a collection of objects representing folders. I would like to let the user create folders as they please with the constraint that the app will create a 'root' folder (object) and I would like to control the _id property for this folder. according to the mongoDB documentation I should be able to set the _id field but when I try I get an error:
Cast to ObjectId failed for value "0" at path "_id"
The mongo docs say the _id can be any BSON data type other than array so I don't understand why '0' is not valid. Why can't I use '0' as an _id?
To be clear, I would like mongoDB to generate an id for all other cases other than the root folder.
folder schema:
const mongoose = require('mongoose');
const constants = require('../config/constants');
const { Schema } = mongoose;
const FolderSchema = new Schema(
{
user: {
type: Schema.Types.ObjectId,
ref: 'User',
required: [true, 'Folder must have a user'],
},
name: {
type: String,
required: true,
trim: true,
},
dateCreated: {
type: Date,
default: Date.now,
},
lastUpdated: {
type: Date,
default: Date.now,
},
parentId: {
type: String,
required: true,
},
},
{
toJSON: { virtuals: true },
toObject: { virtuals: true },
},
);
FolderSchema.index({ name: 'text' });
// eslint-disable-next-line func-names
FolderSchema.virtual('id').get(function () {
return this._id.toHexString();
});
module.exports = mongoose.model('Folder', FolderSchema);
You need to declare in your schema what format the _id should have.
Mongoose defaults it to BSON ObjectId, but this can be overwritten as per the docs: (emphasis mine)
You can also overwrite Mongoose's default _id with your own _id. Just be careful: Mongoose will refuse to save a document that doesn't have an _id, so you're responsible for setting _id if you define your own _id path.
const schema = new Schema({ _id: Number });
const Model = mongoose.model('Test', schema);
const doc = new Model();
await doc.save(); // Throws "document must have an _id before saving"
doc._id = 1;
await doc.save(); // works
Applying this to your schema:
const FolderSchema = new Schema(
{
_id: {
type: Number,
required: true,
},
user: {
type: Schema.Types.ObjectId,
ref: 'User',
required: [true, 'Folder must have a user'],
},
name: {
type: String,
required: true,
trim: true,
},
dateCreated: {
type: Date,
default: Date.now,
},
lastUpdated: {
type: Date,
default: Date.now,
},
parentId: {
type: String,
required: true,
},
},
{
toJSON: { virtuals: true },
toObject: { virtuals: true },
},
);

node mongoose update two collections

I have two schemas, a "projects" schema, and an "applications" schema.
What is the most efficient way of creating a new entry in a collection and updating an existing entry in another collection based on data inside the new entry? Can I avoid making multiple API requests and somehow run a "stored procedure" on the mongoDB end to handle updating the Projects collection when there is a change in the Applications collection?
In this scenario, ideally when an application for a project is created, a new entry is created in the Applications collection and the Project in the Projects collection is updated to reflect the information in the Application.
Can I do this without making multiple api requests?
Project Schema:
// models product.js
const mongoose = require('mongoose');
const { ObjectId } = mongoose.Schema;
const projectSchema = new mongoose.Schema({
name: {
type: String,
trim: true,
required: true,
maxlength: 32
},
applications: {
type: Number,
default: 0
},
created_by: {
type: ObjectId,
ref: 'User'
},
applicants: {
type: Array,
default: []
}
}, {timestamps: true}
);
module.exports = mongoose.model("Project", projectSchema);
Application Schema:
const mongoose = require('mongoose');
const applicationSchema = new mongoose.Schema({
applicantId: {
type: ObjectId,
ref: 'User'
},
ownerId: {
type: ObjectId,
ref: 'User'
},
projectId: {
type: ObjectId,
ref: 'Project'
}
}, {timestamps: true});
module.exports = mongoose.model("Application", applicationSchema);
Note that these are separate schemas because they each carry around 15 fields, i've trimmed them down to post this question.
I suggest to use hooks for mongoose model, there is a post save hook which you can use on Application model to update Project and increment application count.
EDIT - Added Pseudo Code
Project Model
// models -> project.js
const mongoose = require('mongoose');
const {
ObjectId
} = mongoose.Schema;
const projectSchema = new mongoose.Schema({
name: {
type: String,
trim: true,
required: true,
maxlength: 32
},
applications: {
type: Number,
default: 0
},
created_by: {
type: ObjectId,
ref: 'User'
},
applicants: {
type: Array,
default: []
}
}, {
timestamps: true
});
projectSchema.statics = {
/**
* Find project by _id
*
* #param {ObjectId} _id
* #api private
*/
get: function (_id) {
return this.findOne({
_id
})
.exec();
}
}
module.exports = mongoose.model("Project", projectSchema);
Application Model
const mongoose = require('mongoose');
const projectModel = require("./project")
const applicationSchema = new mongoose.Schema({
applicantId: {
type: ObjectId,
ref: 'User'
},
ownerId: {
type: ObjectId,
ref: 'User'
},
projectId: {
type: ObjectId,
ref: 'Project'
}
}, {
timestamps: true
});
// Async hook
applicationSchema.post('save', function (doc, next) {
const relatedProject = projectModel.get(doc.projectId);
relatedProject.applications++;
relatedProject.save();
next();
});
module.exports = mongoose.model("Application", applicationSchema);

Referencing Schemas in Mongoose

I have a couple models that are in going to be held in separate files and I can't seem to find a way to reference them without resorting to having them in the same file.
My first file contains the following:
var mongoose = require('mongoose'),
bcrypt = require('bcrypt'),
Schema = mongoose.Schema;
var UserSchema = new Schema({
email: {
type: String,
unique: true,
lowercase: true,
trim: true,
required: true
},
hash_password: {
type: String
},
/* etc */
});
UserSchema.methods.comparePassword = function(password) {
return bcrypt.compareSync(password, this.hash_password);
};
module.exports = mongoose.model('User', UserSchema);
And the second file is this:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var ThreadSchema = new Schema({
title: {
type: String,
required: true,
trim: true
},
created_by: {
type: { type: Schema.Types.ObjectId, ref: 'User' },
required: true
}
/* etc */
});
module.exports = mongoose.model('Threads', ThreadSchema);
I keep getting this error: "TypeError: Undefined type undefined at created_by.required". The code works if I keep the user and thread models in the same file but when I separate the files, they no longer can reference each other. I tried adding require('./userModel') at the top of the threadModel but that didn't work either.
Any help is appreciated.

Resources