Mail Schema:
var mail = new mongoose.Schema({
globalId: {type: String, index: true, unique: true},
from: {type: String, required: true},
beginDate: {type: Date, required: true},
endDate: {type: Date},
source: {type: String},
address: {type: String},
subject: {type: String, required: true},
text: {type: String},
note: {type: String},
files: [
{
fileName: {type: String},
fileSize: {type: Number},
fileType: {type: String}
}
]
});
When I try to save new mail with endDate is null I have the following error
Mail validation failed: endDate: Cast to Date failed for value "null"
It looks like you are trying to save the schema with an invalid endDate.
If you do not want to save a date simply leave it out from the object. For instance all you need to provide for your schema at a minimum is:
const newMail = mail.create({
globalId: "1234",
from: "Jack",
beginDate: new Date(),
subject: "Random subject",
});
If you tried to do something like,
endDate: null
this will fail as it is expecting a Date() object or nothing at all.
As you have mentioned that you are storing endDate as null as String. That will definitely fail because your schema expecting a date and you are storing String.
Multiple ways you can approach:
Avoid endDate from JSON object. (You will not have endDate key in MongoDB)
set endDate: undefined that will automatically be ignored. (You will not have endDate key in MongoDB)
Set endDate: null not in String (You will have endDate key as null value)
Below one will not work:
var testObj = {
ct: "null", // null as String value
name: "Foo"
}
But this one will definitely work:
var testObj = {
ct: null, // null as value
name: "Foo"
}
Tested on below version:
MongoDB v3.2.18
Mongoose v4.10.8
Another point I want to add here is storing key: null will consume resources. If your requirement is not dependent on null values, I would like to use not to store a key in the database rather storing as null.
I have solved this by setting the default date to undefined. It will not show up on creation of your object. That is fine as it is now a frontend problem. If a key does not exist the frontend will default to undefined. If it remains undefined it will not be saved in your database. Avoid having a default null I have made that mistake too!
mail = {
endDate: {
type: Date,
default: undefined
}
}
In your schema you can mention the type as endDate : { type: Date || null} and wherever you feel like assign the value as null if date is not there OR you can even add default as null to schema.
Related
Below is my mongoose Schema out of which createdOn is of type date and default to Date.now().
const SurveyResponseModel = mongoose.Schema({
surveyId: { type: String, required: true },
surveyData: [surveyData],
result : [respResult],
patientId: { type: String },
surveyBy: {type: String},
createdOn: { type: Date, default: Date.now() },
});
Here is how I'm adding new entries to the db.
const newSurvey = new surveyResponseModel({ surveyId, surveyData, surveyBy, patientId, result })
let savedSurvey = await newSurvey.save();
Up until here everything works fine. The problem starts when new entries are made into the schema. I get the same timestamp of createdOn for each new entries.
What am I doing wrong? Is it createdOn: { type: Date, default: Date.now() } a issue or something else. Is it a problem with MongoDB or my node express server? Some help and feedback would really be appreciated.
When this code is executed (at server startup), Date.now() is executed and the result is saved in the object literal, hence that single timestamp will be used for the duration of the server's life.
Try passing the function instead of a value it returns at a single point in time. Mongoose will then call it at runtime.
createdOn: { type: Date, default: Date.now }
Because I cannot edit properties of a non-lean mongoose result, I've used the result.toObject() statement, but that also means I cannot use the methods defined on my Schema.
Example
// Defining the schema and document methods
const User = new Schema({
email: {type: String, required: true, unique: true},
firstname: {type: String, required: true},
registration_date: {type: Date, default: Date.now, required: true},
insert: {type: String},
lastname: {type: String, required: true}
});
User.methods.whatIsYourFirstName = function () {
return `Hello, my firstname is:${this.firstname}`;
};
After a find:
user = user.toObject();
user.registration_date = moment(user.registration_date);
user.whatIsYourFirstName();
// result in "user.whatIsYourFirstName is not a function"
Is this solvable?
Methods and Models are part of Mongoose, not MongoDB.
Whenever you are calling .toObject() you are being returned an object which is ready for storage in MongoDB.
If you do need to do any sort of value transformation, I'd do it just before you deliver the value to the user. Being a time formatting, if you are building an API, I'd do that in the client; if you are working with templates try transforming the value on the same template.
I am trying to write a schema that takes the parameters required by an activity. I am want to add a field 'activityParameters' that will be case specific depending on the activityType. Suppose if the activityType is email then the activityParameters should store details like'to:String, from:String, subject: String, body: String' and if the activity is "export" then it should store parameters like 'path:String' . Different types of activity will have different parameters. Please help me how to do this.
var activity_type = {
values: 'email export'.split(' '),
message: 'validation failed for path `{PATH}` with value `{VALUE}`'
};
var activitySchema = new Schema({
activityName: String,
activityDescription: String,
executionTime: {type: Date , default: null},
activityStartTime: {type: Date , default: null},
activityCompletionTime: {type: Date , default: null},
activityType: {type:String, enum: activity_type},
//activityParameters: ,
appName : String,
activityRetryCount: {type:Number,default:0},
createdOn: {type:Date , default:Date.now},
deletedOn: {type: Date , default: null},
updatedOn: {type: Date , default: null}
});
There's really no good answer for doing this with mongoose and maintaining a strongly typed schema.
You can specify all the fields for each type on the schema and then use them depending on type (export vs message).
var activitySchema = new Schema({
...
activityParameters: {
to:String,
from:String,
path:String
}});
You might consider having a key per subtype to be an improvement:
var activitySchema = new Schema({
...
emailActivityParameters:{
to:String,
from:String,
},
exportActivityParameters:{
path:String,
}
});
It would be pretty easy to access each "subdocument" depending on the activity type.
Finally, you can have a key called activityParameters and have that be freeform json:
var activitySchema = new Schema({
...
activityParameters: {}
});
In this case you can preserve your schema integrity using custom validators.
If these approaches don't appeal then maybe mongoose isn't the right tool you. You could use a lower level mongo driver and then something like Typescript or json schema to validate your models before you save them to mongoose. Check out this, for example: https://github.com/litixsoft/lx-valid.
I have a problem with displaying data with sorting. Here is my query,
Activity.find({"user_id": sesUser._id}, {}, {offset: 0, limit : 5, sort:{createdAt:1}}, function (e,a){
...
});
I have data about 252 length, and my latest data is 9 June 2015. If i use this query i only get data from 5 June 2015/ last week data and not get the latest data, but if i not using sorting, the latest data is appear.
I have used this query below but turns out the result is same.
Activity.find({"user_id" : sesUser._id}).sort("createdAt").exec(function(err,a){
...
});
Any help? I'm using Mongoose v3
-- edited --
This is my Activity Schema / Model
var mongoose = require('mongoose');
var Activity = mongoose.Schema({
sender_id : {type: String, required: true },
user_id : {type: String, required: true },
product_id : {type: String, default : "" },
type : {type: String, required: true },
createdAt : {type: String, default : new Date()}
});
module.exports = mongoose.model('Activity', Activity);
`createdAt : {type: Date, default : new Date()}`
Type Date not string man
It will automatically create the createdAt and updatedAt
var options={
timestamps: true
}
var Activity = mongoose.Schema({
sender_id : {type: String, required: true },
user_id : {type: String, required: true },
product_id : {type: String, default : "" },
type : {type: String, required: true }
},options);
here's my photoSchema. it has a dbEntry object. should I create another dbEntry schema and ref it in the photoSchema. Or whatever I have is good enough? I am new to mongodb, try to figure out a correct way to create schema.
var photoSchema = new mongoose.Schema({
userId: ObjectId,
type: String,
createdOn: {type: Date, default: Date.now},
isDeleted: {type: Boolean, default: false},
isDownloaded: {type: Boolean, default: false},
dbFile: String,
dbEntry: {
revision: Number,
rev: String,
thumb_exists: Boolean,
bytes: Number,
modified: Date,
client_mtime: Date,
path: { type: String, unique: true}
}
});
It depends on how you plan to access the data. If you want to get the dbEntry object each time you query a photoSchema document, then what you have is probably the way to go.
If however, you're going to use dbEntry independent of the photoSchema document, then you should split it up and just keep a ref to it.
You can always fetch the ref using mongoose "populate"