How to guarantee an array on a Document never has undefined/null in it?

Hello everyone,

We’re having issues with hard-to-catch null and undefined values appearing in some of our arrays in our DB. It causes issues with our unique indexes, which sometimes make our app crash as it detects 2 null values in the DB at that spot.

The simple schema usually looks like this:

const schema = {
        arr: { type: Array, defaultValue: [] },
        'arr.$': Object,
        'arr.$._id': String,
}

And somehow, sometimes it lets a value in this array be null.

One way to do this is like so:

      const _id = collection.insert({ arr: [{ _id: 'hi' }] });
      collection.update({ _id }, { $unset: { 'arr.0': true } });

This results in the following array: [null].

Does someone know of a perfectly reliable way to always avoid this? I’ve tried to write autoValue and custom() functions, but they seem to become unreasonably complex for something that seems quite simple at first. Though I might not’ve found the right one.

1 Like

I need to make sure the null/undefined value never even makes it into the DB, I can’t remove it afterwards, or else I can already have a DB clash.

Here’s the autoValue I thought of:

const makeCleanArrayField = fieldName => ({
  type: Array,
  autoValue() {
    if (this.key !== fieldName && this.key.startsWith(fieldName)) {
      // With an autoValue on the array, of an array of objects
      // this function is also called when you edit a subitem in the array,
      // like with { $unset: { "arr.0": true } }

      // What to do here? And are there other cases
      return;
    }
    if (this.isInsert && !this.isSet) {
      return [];
    }

    if (this.isSet) {
      if (Array.isArray(this.value)) {
        return this.value.filter(Boolean);
      }
      return [];
    }
  },
});

I think it is enough to avoid any source of null. Replacing $unset with $set + $slice should do just that. I think your problem is a problem of all and it doesn’t require a solution but just to avoid it.

The problem with $unset is that the schema validation only sees the modifiers BEFORE the query and it does not see the result AFTER

You might need to use mongodb triggers if you need to check AFTER the query runs