question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Mongoose trying to use set function to fields that are missing

See original GitHub issue

Versions: Node.js: 14.17.5 Mongoose: 5.13.7 MongoDB: 4.4.8

Problem: Mongoose trying to use set function to fields that are missing.

Schema:

const {Schema, Document} = require('mongoose')
const {dateNowWithoutMs, clearStringFromSpaces} = require('../utils/setData')

const toInt = value => {
  return value ^ 0
}
const eventSchema = new Schema({
    title: {type: String, minlength: 3, maxlength: 100, set: clearStringFromSpaces},
    startDate: {type: Number, min: dateNowWithoutMs(), max: dateNowWithoutMs() * 2, set: toInt},
    endDate: {type: Number, min: dateNowWithoutMs(), max: dateNowWithoutMs() * 2, set: toInt},
    _apperDate: {type: Number, default: dateNowWithoutMs(), select: false},
    __v: {type: Number, select: false}
})
eventSchema.statics ={
  create: async function({ title = 'Default' , startDate, endDate }) {
    let event = new this({
      title,
      startDate,
      endDate,
      _apperDate: dateNowWithoutMs()
    })
    console.log('Event presaved:', event) //Result will be presented below 
    event = await event.save()
    return event
  }
}
eventSchema.set(
    'toJSON',
    {
        getters: true,
        transform: function(doc, ret) { 
            delete ret._id
        }
    }
)
module.exports = eventSchema

Example code:

const db = require('../db')

const test = async() => {
  const data = {
    title: 'test'
  }
  const event = await db.Event.create(data)
}

test()

Console.:

Event presaved: {
  title: "test",
  _id: 613fa66056fd93333499f711,
  _apperDate: 1631561312
}

Error text:

Event validation failed: startDate: Cast to Number failed for value \"NaN\" (type number) at path \"startDate\", endDate: Cast to Number failed for value \"NaN\" (type number) at path \"endDate\"

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:7

github_iconTop GitHub Comments

1reaction
vkarpov15commented, Sep 25, 2021

This is expected behavior because you’re explicitly setting startDate and endDate to undefined. When you do new this({ startDate, endDate }), that means you’re always setting startDate and endDate. I’d recommend you do this instead:

const toInt = value => {
  if (value == null) { // <-- add this to handle if `value` is nullish
    return value
  }
  return parseInt(value)
}

const eventSchema = new Schema({
    // Add `default` below
    title: {type: String, minlength: 3, maxlength: 100, set: clearStringFromSpaces, default: 'Default' }, 
    startDate: {type: Number, min: dateNowWithoutMs(), max: dateNowWithoutMs() * 2, set: toInt},
    endDate: {type: Number, min: dateNowWithoutMs(), max: dateNowWithoutMs() * 2, set: toInt},
    _apperDate: {type: Number, default: dateNowWithoutMs(), select: false},
    __v: {type: Number, select: false}
})
eventSchema.statics ={
  create: async function(obj) {
    let event = new this({
      ...obj, // <-- avoid explicitly setting `startDate` and `endDate` if they aren't set
      _apperDate: dateNowWithoutMs()
    })
    console.log('Event presaved:', event) //Result will be presented below
    event = await event.save()
    return event
  }
}
0reactions
R00tCropcommented, Sep 15, 2021

Here is the complete test code:

const mongoose = require('mongoose');
const {Schema, Document} = mongoose;

const dateNowWithoutMs = () => {
    return Date.now() / 1000 ^ 0
}
const clearStringFromSpaces = string => {
    return string.trim().replace(/\s+/ig, ' ')
}
const toInt = value => {
  return parseInt(value)
}

const eventSchema = new Schema({
    title: {type: String, minlength: 3, maxlength: 100, set: clearStringFromSpaces},
    startDate: {type: Number, min: dateNowWithoutMs(), max: dateNowWithoutMs() * 2, set: toInt},
    endDate: {type: Number, min: dateNowWithoutMs(), max: dateNowWithoutMs() * 2, set: toInt},
    _apperDate: {type: Number, default: dateNowWithoutMs(), select: false},
    __v: {type: Number, select: false}
})
eventSchema.statics ={
  create: async function({ title = 'Default' , startDate, endDate }) {
    let event = new this({
      title,
      startDate,
      endDate,
      _apperDate: dateNowWithoutMs()
    })
    console.log('Event presaved:', event) //Result will be presented below 
    event = await event.save()
    return event
  }
}
eventSchema.set(
    'toJSON',
    {
        getters: true,
        transform: function(doc, ret) { 
            delete ret._id
        }
    }
)

const Test = mongoose.model('Test', eventSchema);

async function test() {
    await mongoose.connect('mongodb://localhost:27017/', {useNewUrlParser: true,
    useUnifiedTopology: true,});
    await mongoose.connection.dropDatabase();
    await Test.create({
        title: 'test'
    });
}

test();
Read more comments on GitHub >

github_iconTop Results From Across the Web

Nodejs Mongoose still return fields if missing - Stack Overflow
In this case you can add default in your schema. If you do this, an empty string is saved by default for that...
Read more >
Setting and getting fields not defined in schema not working ...
What is the expected behavior? I was expecting to remove the fields set as undefined from the database. I did put the full...
Read more >
$exists — MongoDB Manual
To query for null or missing fields, see Query for Null or Missing Fields. Use a Sparse Index to Improve $exists Performance. The...
Read more >
Express Tutorial Part 3: Using a Database (with Mongoose)
The very first thing we want to do is set up a MongoDB database that we can use to store our library data....
Read more >
Mongoose v6.8.1: Defaults
Your schemas can define default values for certain paths. If you create a new document without that path set, the default will kick...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found