Please, correct me if my design is not recommended:
I have a model for blog posts with a field "category". I want the user to be able to type the category (with typeahead) and, if the category isn't there, the user would be able to create it. However, in order to prevent unorganized entries, I want to populate the field "category" with a list of categories.
Question is, should I use field "category" as an array or as a sub-document referenced to another model called "Category"? I am assuming the latter would be the recommended design, because it avoids code replication and makes easy the interaction necessary for the user to add a new category.
Now, if I use it with sub-documents, how could I initialize the model "Category" with a list of categories on server startup?
Why don't you use something like this.
//Category schema
//Store all the categories available in this collection
var categorySchema=new Schema({
_id:String,//name of category
description:String
//other stuff goes here
})
mongoose.model(categorySchema, 'Category')
//blog post schema
var postSchema=new Schema({
//all the relevant stuff
categories:[{type:String,ref:'Category'}]
})
Now whenever posting a blog post
, check if the categories
given are already present in the Category
collection. This will be fast as we are using the category name(_id
) as the index itself. So for every new category you should insert in the Category
collection and then insert the blog post
. This way you can populate
the categories
array if required.
To initialise the categories, it can be done by parsing a JSON
file which is more readable . The file should be parsed only when we set off with an empty database i.e when we drop the Categories collection
Create a Categories.json file. Contents of Categories.json:
[
{
_id:'Category1',//name of category
description:'description1'
...
},
{
_id:'Category2',//name of category
description:'description2'
...
},{
_id:'Category3',//name of category
description:'description3'
...
}
...
]
To read the data from file
fs=require('fs');
var buildCategories=fs.readFile(<path to Categories.json>,'utf8',function(err,data){
if (err) {
//logger.error(err);
return ;
}
var datafromfile=JSON.parse(data);
data.forEach(function(obj){
var catOb=new Category(obj)
obj.save(function(err,doc){..});
})
});
//To initialize when the Category collection is empty
Category.findOne({},function(err,doc){
if(!doc){
//Collection is empty
//build fomr file
buildCategories();
}
});
//Or you can just manually call the function whenever required when server starts
buildCategories();
You could argue that you can import a csv file. But this was how I did for my project.
In my case instead of buildCategories
- I've added schema method and just import initialData
from json file (no need to fs.readFile
).
Category.methods = {
async setInitialData() {
return this.collection.insertMany(initialData, err => {
if (err){
return console.error(err);
}
console.log("Initial documents inserted to Category Collection");
});
}}
Then in the controller:
Category.findOne({}, async (err,doc) => {
if(!doc){
const category = new Category();
await category.setInitialData();
}});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With