Mongoose- How can I create a collection with the default values? - node.js

I am creating a schema with the following code;
var Repository = require('./base/Repository');
var Connection = require('./base/Connection');
var scm = Repository.schema({
userId : String,
text: String,
date: Number });
scm.index({date:1}); scm.index({userId:1});
var repo = Repository.create('Feedback', scm, Connection);
module.exports = new repo();
But I want to give default values for the fields while creating this schema. For example I want something like that ;
var scm = Repository.schema({
userId : 12334455,
text: hello world,
date: 19.04.2018 });
How can I manage this with Mongoose ?

You can always specify default values while defining your schema. Like
Repository.schema({
userId : { type: String, default: '12334455' },
text: { type: String, default: 'Xyx' },
date: { type: String, default: 12334455 }
})
Here is documentation

Try this:
http://mongoosejs.com/docs/defaults.html
you may wish to use the setDefaultsOnInsert option.

Related

How can I make a mongo document filed read-only in mongoose schema field declaration? [duplicate]

Short and clear: is there any way to prevent setting a schema field but allowing to get the value?
I've been around the Mongoose Documentation but can't find what I'm looking for.
An alternative if you want to set a default value that can never be changed:
var schema = new Schema({
securedField: {
type: String,
default: 'Forever',
set: function (val) { return this.securedField; }
});
Define the field as a virtual getter instead of a traditional field.
For example, say you wanted to make the pop field of your collection read-only when accessed via Mongoose:
var schema = new Schema({
city: String,
state: String
});
schema.virtual('pop').get(function() {
return this._doc.pop;
});
By accessing the private _doc member of your model instance it's possible this may break in the future, but this worked fine when I tested it just now.
Since mongoose 5.6 you can do: immutable: true
var schema = new Schema({
securedField: {
type: String,
default: 'Forever',
immutable: true
}
});
You can just return from set the same value as the default value, no need to reference the _this document:
var schema = new Schema({
securedField: {
type: String,
default: 'Forever',
set: () => 'Forever'
});

change the default output format mongoose nodejs

my schema in node js
var itemSchema = new mongoose.Schema({
name: { type: String, required: true },
value: { type: String }
});
while doing find, the following result comes,
Item.find().exec(callback); gives result
[{"one":1},{"two":2},{"three":1},{"four":1}]
but i want the result like this,
[{"one":1,"two":2,"three":3,"four":4}]
Is there only way iterate and form the result ?
Please suggest me!

mongoose default value equal to other value

For my project i've created an userSchema which simplified looks like the following:
var userSchema = new Schema({
_id: String,
screenname: {type: String, required: false, default: "equal _id"},
});
The user has an _id that is a string which also is his username.
Everything works so far until i tried to add an extra field screenname. What i want is when the user creates an account, his screenname equals the value of _id. Later he can adjust it but by default it should equal the value of _id. i've also tried :
screenname: {type: String, required: false, default: _id},
But than ofcourse _id is not defined.
How should i set the default value to equal another value ?
use the pre middleware explained here
userSchema.pre('save', function (next) {
this.screenname = this.get('_id'); // considering _id is input by client
next();
});
You can pass a function to default, following is a schema field excerpt:
username: {
type: String,
required: true,
// fix for missing usernames causing validation fail
default: function() {
const _t = this as any; // tslint:disable-line
return _t.name || _t.subEmail;
}
},

Storing a User Provided Date in Mongoose

So, I've got this schema:
var imageSchema = new Schema( {
caption: {type: String, required: true},
url: {type: String, required: true}
});
var EventSchema = new Schema({
name: {type: String, required: true},
date: {type: Date, required: true},
time: {type: String, required: true},
location: {type: String, required: true},
description: { type: String, required: false },
image: {type: String, required: false},
images: [imageSchema]
});
Requests are handled via locomotive.js, and the controller action for creating new records looks like this:
EventController.create = function() {
if(preScreen.screen.bind(this)("event", "create")) {
this.elements = modelHelper.loadValues.bind(this)();
this.saveMessage = "Save";
this.strings = strings;
if(this.req.method && this.req.method == "POST")
{
this._createEvent();
} else {
this.render();
}
} else {
this.redirect(this.urlFor({controller: "dashboard", action: "error"}));
}
};
This is a fairly standard action controller; mostly invoking an input view or or handling the _create when the received with a POST header.
the _createEvent function looks like this:
EventController._createEvent = function() {
if(!(this.elements)) this.elements = require('../templates/Event/elements')();
if(!(this.event)) this.event = new Event();
modelHelper.populate.bind(this)(this.elements, "event", function() {
modelHelper.save.bind(this)("event", this._confirm.bind(this), "create");
}.bind(this));
};
For my models I encapsulate all of the inputs in a template pattern. Rather than spend a lot of time on the framework around this (which I am working on releasing open source once I have finished doing small tweaks too) I will say that effectively the template contains one element for each path in the schema and provides some client-side details (error messages, labels etc.) these template objects are used by a modelHelper object which is fairly agnostic. Effectively what modelHelper.populate does is inspect the "type" property of each object within elements, and calls a handler for the appropriate input type.
the handler for date types is:
case "date" :
this[record][field.name] = strings.exists(this.param(field)) ?
strings.trim(this.param(field.name)) : null;
break;
although I've also tried strings.trim(Date.parse(this.param(field.name)) to get the UTC Timestamp from the user string.
I've been able to validate that the user entered date string does return a valid UTC stamp by using console.log within the date parser.
When the modelHelper.save() call is made it runs through these template objects, creates an associate array with the values picked up from the parsers and passes it to Record.save().
Most of this has been thoroughly tested and is being used in production however this is my first scenario where I am using dates other than date.now() as a default value.
What is the correct body for the date parser in order for mongodb/ the mongoose driver to push a date into a Date type?
Any string that JavaScript's Date.parse method can parse will work as the string is cast to a Date by Mongoose using this function which calls the Date constructor which uses Date.parse to parse strings.

Make all fields required in Mongoose

Mongoose seems to default to make all fields not required. Is there any way to make all the fields required without changing each of:
Dimension = mongoose.Schema(
name: String
value: String
)
to
Dimension = mongoose.Schema(
name:
type: String
required: true
value:
type: String
required: true
)
It'll get really ugly since I have a lot of these.
You could do something like:
var schema = {
name: { type: String},
value: { type: String}
};
var requiredAttrs = ['name', 'value'];
for (attr in requiredAttrs) { schema[attr].required = true; }
var Dimension = mongoose.schema(schema);
or for all attrs (using underscore, which is awesome):
var schema = {
name: { type: String},
value: { type: String}
};
_.each(_.keys(schema), function (attr) { schema[attr].required = true; });
var Dimension = mongoose.schema(schema);
I ended up doing this:
r_string =
type: String
required: true
r_number =
type: Number
required: true
and on for the other data types.
All fields properties are in schema.paths[attribute] or schema.path(attribute);
One proper way to go : define when a field is NOT required,
Schema = mongoose.Schema;
var Myschema = new Schema({
name : { type:String },
type : { type:String, required:false }
})
and make them all required by default :
function AllFieldsRequiredByDefautlt(schema) {
for (var i in schema.paths) {
var attribute = schema.paths[i]
if (attribute.isRequired == undefined) {
attribute.required(true);
}
}
}
AllFieldsRequiredByDefautlt(Myschema)
The underscore way :
_=require('underscore')
_.each(_.keys(schema.paths), function (attr) {
if (schema.path(attr).isRequired == undefined) {
schema.path(attr).required(true);
}
})
Test it :
MyTable = mongoose.model('Myschema', Myschema);
t = new MyTable()
t.save()
Well you could write a mongoose schema plugin function that walked the schema object and adjusted it to make each field required. Then you'd just need 1 line per schema: Dimension.plugin(allRequired).
Mongoose didn't provide the method of setting all fields, but you could do it recursively.
Like Peter mentioned, you could pluginize it in order to reuse the code.
Recursively setting:
// game.model.js
var fields = require('./fields');
var Game = new Schema({ ... });
for(var p in Game.paths){
Game.path(p).required(true);
}
Pluginized:
// fields.js
module.exports = function (schema, options) {
if (options && options.required) {
for(var p in schema.paths){
schema.path(p).required(true);
}
}
}
// game.model.js
var fields = require('./fields');
var Game = new Schema({ ... });
Game.plugin(fields, { required: true });
I'm not sure if there's an easier way to do it in Mongoose, but I would do the following in your IDE/editor:
List out your fields as you would normally:
Dimension = mongoose.Schema(
name: String
value: String
)
Then do a find and replace on String and replace it with {type: String, required: true}, Giving you:
Dimension = mongoose.Schema(
name: {type: String, required: true},
value: {type: String, required: true},
)
Then do the same for Number and other types.
Building on the previous answers, the module below will make fields required by default. The previous answers did not recurse nested objects/arrays.
Usage:
const rSchema = require("rschema");
var mySchema = new rSchema({
request:{
key:String,
value:String
},
responses:[{
key:String,
value:String
}]
});
Node module:
const Schema = require("mongoose").Schema;
//Extends Mongoose Schema to require all fields by default
module.exports = function(data){
//Recursive
var makeRequired = function(schema){
for (var i in schema.paths) {
var attribute = schema.paths[i];
if (attribute.isRequired == undefined) {
attribute.required(true);
}
if (attribute.schema){
makeRequired(attribute.schema);
}
}
};
var schema = new Schema(data);
makeRequired(schema);
return schema;
};

Resources