Reputation: 3607
I would like to only have a versioneditems
collection in MongoDB but I need to register both the VersionedItem
model and the ItemPatch
model because I need to create ItemPatch
es to populate a VersionedItem
.
There will be no separate ItemPatch
documents (they are embedded in a VersionedItem
). The code below is working except for the fact that an extra collection is created in MongoDB:
src/models/versionedItemFactory.js
const VersionedItemSchema = require('../schemas/VersionedItem');
module.exports = (db) => {
var VersionedItemModel = db.model('VersionedItem', VersionedItemSchema);
return VersionedItemModel;
};
src/models/itemPatchFactory.js
const ItemPatchSchema = require('../schemas/ItemPatch');
module.exports = (db) => {
var ItemPatchModel = db.model('ItemPatch', ItemPatchSchema);
return ItemPatchModel;
};
src/schemas/util/asPatch.js
var mongoose = require('mongoose');
module.exports = function _asPatch(schema) {
return new mongoose.Schema({
createdAt: { type: Date, default: Date.now },
jsonPatch: {
op: { type: String, default: 'add' },
path: { type: String, default: '' },
value: { type: schema }
}
});
};
src/schemas/Item.js
var mongoose = require('mongoose');
module.exports = new mongoose.Schema({
title: { type: String, index: true },
content: { type: String },
type: { type: String, default: 'txt' }
}, { _id: false });
src/schemas/ItemPatch.js
var asPatch = require('./util/asPatch');
var ItemSchema = require('./Item');
module.exports = asPatch(ItemSchema);
src/schemas/VersionedItem.js
var mongoose = require('mongoose');
var ItemPatchSchema = require('./ItemPatch');
module.exports = new mongoose.Schema({
createdAt: { type: Date, default: Date.now },
patches: [
{
createdAt: { type: Date, default: Date.now },
jsonPatch: { type: ItemPatchSchema }
}
]
});
Then registering like so:
db.once('open', function() {
require('./models/itemPatchFactory')(db);
require('./models/versionedItemFactory')(db);
});
I need to register the ItemPatch
model via itemPatchFactory
because I want to be able to populate a versioned item like so:
var itemPatch = new db.models.ItemPatch({
jsonPatch: {
op: 'add',
path: '',
value: {
title: 'This is a title',
content: 'This is content',
type: 'txt'
}
}
});
var itemPatch2 = new db.models.ItemPatch({
jsonPatch: {
value: {
title: 'This is a title 2',
content: 'This is content 2'
}
}
});
var versionedSomething = new db.models.VersionedItem();
versionedSomething.patches.push(itemPatch);
versionedSomething.patches.push(itemPatch2);
versionedSomething.save(function (err, result) {
if (err) throw err;
console.log('result:', result);
});
This successfully creates the versioned item with the 2 patches in it, but an (empty) itempatches
collection is created in MongoDB and I'd like to avoid that.
Upvotes: 8
Views: 3885
Reputation: 805
You can't create a Model
without a corresponding collection, but I don't think you actually need to in order to do what you want.
You can simply create a javascript object for the child and push it to the parent collection. See this snippet from the Mongoose docs (https://mongoosejs.com/docs/subdocs.html)
var Parent = mongoose.model('Parent');
var parent = new Parent;
// create a comment
parent.children.push({ name: 'Liesl' });
var subdoc = parent.children[0];
console.log(subdoc) // { _id: '501d86090d371bab2c0341c5', name: 'Liesl' }
subdoc.isNew; // true
parent.save(function (err) {
if (err) return handleError(err)
console.log('Success!');
});
You can create a Schema
for the subdocument, however. That will let you enforce the structure when reading/writing from the parent collection:
var childSchema = new Schema({ name: 'string' });
var parentSchema = new Schema({
// Array of subdocuments
children: [childSchema],
// Single nested subdocuments. Caveat: single nested subdocs only work
// in mongoose >= 4.2.0
child: childSchema
});
Upvotes: 2
Reputation: 2533
You can use the mongoose Schema options - autoCreate: false, autoIndex: false to not create the mongodb collection.
[1] https://mongoosejs.com/docs/guide.html#autoIndex
Upvotes: 2