4

I want to store a load of arrays in mongoose on Node. I want to be sure those arrays contain a unique collection of numbers. Here's my Schema:

var schema = new Schema({
    array: { type: [Number], unique: true, required: true }
});

It doesn't work. For example, creating and saving a couple of new db models that have a couple of (what I would call unique) arrays:

new Model({ array: [1,2] })
new Model({ array: [0,2] })

...causes this:

E11000 duplicate key error index: test2.modes.$array_1  dup key: { : 1 }

..so it looks like 'unique' is checking every index in those arrays for uniqueness, rather than the entire array as being unique.

Is there another way to do this in one step? Or do I have to perform a find on the db, say inside of a schema.pre('save', fn), to check the arrays are unique?

stephband
  • 2,594
  • 2
  • 23
  • 33
  • Doesn't look like it. See possible dupe of http://stackoverflow.com/questions/6743849/mongodb-unique-index-on-array-elements-property. – JohnnyHK Sep 03 '12 at 03:33
  • Yes, I did see that question. Looking at it again, I guess it may be talking about the same thing, but the reference to sub documents (kittens) confused me. MongoDB noob. – stephband Sep 03 '12 at 03:38
  • Seems it's the compound variant of the same issue. Using the `$addToSet` operator when updating your arrays may be useful to you depending on your overall use case. – JohnnyHK Sep 03 '12 at 03:45
  • The arrays themselves will be set in stone - they won't change once they're generated. – stephband Sep 03 '12 at 03:50

1 Answers1

4

Ok, so in lieu of a better way, this is how I've solved it, using a save hook and an extra string:

var schema = new Schema({
    array: { type: [Number], required: true }
    _arraySignature: { type: String, unique: true }
});

schema.pre('save', function(next) {
    this._arraySignature = this.array.join('.');
    next();
});

...but I can only do this because I know that my arrays will be sorted, never contain more than one of the same number, and immutable. It's a bit fugly. I'd love to know if there's a better way.

stephband
  • 2,594
  • 2
  • 23
  • 33