Skip to content

Instantly share code, notes, and snippets.

@robert52
Last active June 18, 2024 00:11
Show Gist options
  • Save robert52/1f82b5d201aa95e13cd1a3344f03eda5 to your computer and use it in GitHub Desktop.
Save robert52/1f82b5d201aa95e13cd1a3344f03eda5 to your computer and use it in GitHub Desktop.
Approaches to create and combine models in mongoose. Document referencing, model composition and many more.
'use strict';
const DEF_CURRENCY = 'USD';
const DEF_SCALE_FACTOR = 100;
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const ObjectId = Schema.ObjectId;
const MoneySchema = new Schema({
amount: { type: Number, default: 0 },
currency: { type: String, default: DEF_CURRENCY },
factor: { type: Number, default: DEF_SCALE_FACTOR }
}, {
_id: false,
toObject: { virtuals: true },
toJSON: { virtuals: true }
});
// implements exact precision model
MoneySchema
.virtual('value')
.set(function(value) {
if (value) {
this.set('amount', value * this.factor);
}
})
.get(function() {
return this.amount / this.factor;
});
module.exports = mongoose.model('Money', MoneySchema);
'use strict';
const mongoose = require('mongoose');
const Money = require('./money.model').schema;
const Schema = mongoose.Schema;
const ObjectId = Schema.ObjectId;
const Mixed = Schema.Types.Mixed;
const OrderSchema = new Schema({
identifier: { type: String },
user: { type: ObjectId, ref: 'User' },
status: { type: String, default: 'active' },
total: { type: Money },
details: { type: Mixed },
shipping: { type: Mixed },
items: { type: [
{
sku: { type: String },
qty: { type: Number, default: 1},
title: { type: String },
price: { type: Money },
product: { type: ObjectId, ref: 'Product' }
}
]},
expiresAt: { type: Date, default: null },
updatedAt: { type: Date, default: Date.now },
createdAt: { type: Date, default: Date.now }
}, {
toObject: { virtuals: true },
toJSON: { virtuals: true }
});
module.exports = mongoose.model('Order', OrderSchema);
'use strict';
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const ObjectId = Schema.ObjectId;
const ProductDetailSchema = new Schema({
title: { type: String, required: true },
description: { type: String },
summary: { type: String, required: true }
}, {
_id: false,
strict: false,
toObject: { virtuals: true },
toJSON: { virtuals: true }
});
module.exports = mongoose.model('ProductDetail', ProductDetailSchema);
'use strict';
const mongoose = require('mongoose');
// your common helpers file
const commonHelper = require('../helpers/common');
// custom schema
const Money = require('./money.model').schema;
const ProductDetail = require('./product-detail.model').schema;
const Schema = mongoose.Schema;
// mongoose schema
const ObjectId = Schema.ObjectId;
const Mixed = Schema.Types.Mixed;
const ProductSchema = new Schema({
sku: { type: String, required: true },
category: { type: String },
slug: { type: String },
images: { type: [
{
caption: { type: String },
filename: { type: String }
}
] },
details: { type: ProductDetail },
price: { type: Money },
active: { type: Boolean, default: false }
});
ProductSchema.pre('save', function(next) {
// generic `slug` creation method
this.slug = commonHelper.createSlug(this.title);
next();
});
ProductSchema.statics.findBySKU = function findBySKU(sku, callback) {
this.findOne({ sku: sku }, callback);
}
ProductSchema.statics.findBySlug = function findBySlug(sku, callback) {
this.findOne({ slug: slug }, callback);
}
module.exports = mongoose.model('Product', ProductSchema);
'use strict';
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const UserSchema = new Schema({
email: {
type: String,
required: true,
unique: true
},
name: {
type: String
},
password: {
type: String,
required: true,
select: false
},
passwordSalt: {
type: String,
required: true,
select: false
},
active: {
type: Boolean,
default: true
},
createdAt: {
type: Date,
default: Date.now
}
});
module.exports = mongoose.model('User', UserSchema);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment