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);
Related
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: []
}
})
assuming i have this 2 schemas
company schema with an array of categories
//category
export const CategorySchema = new mongoose.Schema({
name: { type: String },
}, { timestamps: true });
//company
export const CompanySchema = new mongoose.Schema({
user: { type: Schema.Types.ObjectId, ref: 'User' },
name:String,
email:String,
categories:{type: [CategorySchema], default: [] },
}, { timestamps: true });
product schema with category as a ref to the category from company
export const ProductSchema =new mongoose.Schema({
name:String,
category:{ type: Schema.Types.ObjectId, ref: 'Category' },
}, { timestamps: true })
is it possible to populate category from the product ?
i tried this code and it's not working
const products=await this.productModel.find({}).populate({'path':"category","model":"Category"}) ``
what you need is just
productModel.find({}).populate("category")
try this code for populate
const products=await this.productModel.find({}).populate({'path':"category","model":"company.categories"})
currently i created a schema for storing products using mongoose as below
const Schema = mongoose.Schema;
const ProductSchema = new Schema({
title: {
type: String,
required: true
},
price: {
type: Number,
required: true
},
description: {
type: String,
required: true
},
quantity: {
type: Number,
required: true
},
manufacture: {
type: String,
required: true
},
creator: {
type: Schema.Types.ObjectId,
ref: 'user'
},
category: {
type: Schema.Types.ObjectId,
ref: 'category'
}
});
module.exports = { Product: mongoose.model('product', ProductSchema) };
and here another schema for storing categories that products are related to
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const CategorySchema = new Schema({
title: {
type: String,
required: true
}
});
module.exports = { Category: mongoose.model('category', CategorySchema) };
each product is related to a category
the question is how can i display all products that are related to a specific category.
i tried .find() method but i can't use it correctly.
thanks for any advice
You need to use .populate('category'), after .find() in order to populate all the connected data.
products.find().populate('category').exec((err, product) => { })
I am using Mongoose in my NodeJs project. I want to rename my collection from OldCollectionName to NewCollectionName.
I tried following:
Mongoose.connection.collection('OldCollectionName').rename('NewCollectionName');
But this is making my collection empty. Can someone suggest how can I change the collection name without loosing my collection data? I need all the data from OldCollectionName in NewCollectionName as well.
I have following schema for my model
const Mongoose = require('mongoose');
const mongooseSequence = require('mongoose-sequence');
const Schema = Mongoose.Schema;
var collectionSchema = new Schema({
collectionIdAutoIncrement: { type: Number,unique: true,index:true,sparse:true},
fieldName: {
type: String,
default: ''
},
otherCollectionId: {
type: Schema.Types.ObjectId,
required: true,
ref: "OtherCollection",
},
created: { type: Date, default: Date.now },
updated: { type: Date},
});
collectionSchema.plugin(mongooseSequence, { inc_field: 'collectionIdAutoIncrement' });
var oldCollection = Mongoose.model('OldCollectionName', collectionSchema);
The error started after I started using the discriminator.
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const Base = require("../config/Base");
const Refill = Base.discriminator(
"Refill",
new Schema({
cylinderSize: { type: Number, required: true },
cylinderSwap: { type: Boolean, required: true },
quantity: { type: Number, required: true },
location: {
type: { type: String },
coordinates: [Number]
}
})
);
Refill.index({ location: "2dsphere" });
module.exports = mongoose.model("Refill");
This returns the error Refill.index is not a function
In Mongoose, indexes must be created on schemas, not models. In your case, the Refill object is a model. One approach is to implement this in three steps:
Create the schema
Add the index to the schema
Create the model
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const Base = require("../config/Base");
const refillSchema =
new Schema({
cylinderSize: { type: Number, required: true },
cylinderSwap: { type: Boolean, required: true },
quantity: { type: Number, required: true },
location: {
type: { type: String },
coordinates: [Number]
}
});
refillSchema.index({ location: "2dsphere" });
const Refill = Base.discriminator("Refill", refillSchema);
module.exports = mongoose.model("Refill");
I just took out the Refill.index({ location: "2dsphere" }); and the rest of my code is working fine apparently indexing that field wasn't necessary.