简体   繁体   中英

Mongoose saving empty array error “TypeError: Cannot read property '1' of null”

I have a schema that is defined like so:

const userSchema = new Schema({
  ...
  surveys: [surveyKeySchema],
  ...
})

Where surveyKeySchema is actually a subdocument scheme defined like so:

const surveyKeySchema = new Schema({
  slug: {
    type: String,
    required: 'Please supply a slug',
    unique: true,
    lowercase: true,
    trim: true
  },
  name: {
    type: String,
    required: 'Please supply a name',
    trim: true
  },
  responseCount: {
    type: Number,
    default: 0
  }
})

Now whenever I try to modify anything on the user except for this array, everything goes fine. When instantiating the user, it is also totally fine. I can also call await user.save() in my code right before I empty the array.

It's also fine when I remove any subdocument from the survey as long as there is at least 1 element remaining.

However, when I try to remove the final subdocument using:

      await user.surveys.id(sid).remove()
      await user.save()

I get an error on the .save() which is just TypeError: Cannot read property '1' of null . I'm confused and can't find anything about this online, I assume it must be requiring at least one subdocument to be present? Is there any way to remove this, or if my assumption is wrong how would I go about resolving this?

Thanks in advance! And my apologies if I'm missing something obvious!

EDIT:

I found that mongoose's mongo error handler was actually throwing this in a regex it was using to parse the error message. Hacking this around to return the raw error message:

E11000 duplicate key error index: db.users.$surveys.slug_1 dup key: { : null }

As per this question I tried adding sparse: true but this didn't work.

For anyone else having this issue, here's what I did:

  1. In node_modules/mongoose-mongodb-errors/lib/plugin.js on line 19, add a simple console.error(err.message) so you can actually get the output and not the regex handler error.

  2. Because when you save an empty array of subdocuments in Mongoose it is equivalent to having the subschema set to values of null, this means that when Mongoose evaluates the indices of your subdocument collection it will evaluate it as having a value of null for each property. If you're indexing with a property (ie one of the properties in your subdocument schema has unique: true on it) then this is a violation as a null value cannot be unique, at least not in Mongo world. To get around this you can add sparse: true .

  3. Any documents in the existing collection and the existing collection itself will create an issue with now having a changed index. You need to drop the index for this to work. I dropped the entire collection because I didn't need it anyways.

Here's my updated schema:

const surveyKeySchema = new Schema({
  slug: {
    type: String,
    required: 'Please supply a slug',
    unique: true,
    lowercase: true,
    sparse: true,
    trim: true
  },
  name: {
    type: String,
    required: 'Please supply a name',
    trim: true
  },
  responseCount: {
    type: Number,
    default: 0
  }
})

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM