Non-Permeable Membrane

    mongoose-unique-array

    0.4.2 • Public • Published

    mongoose-unique-array

    Mongoose plugin for enforcing unique constraints in arrays

    CircleCI

    Usage

    Requires mongoose >= 4.10.0. Do not use with mongoose 3.x.

    const arrayUniquePlugin = require('mongoose-unique-array');

    API

    Basic Example

    If you set the unique property to true on a schema path, this plugin will add a custom validator that ensures the array values are unique before saving.

        const schema = new mongoose.Schema({
          arr: [{ type: String, unique: true }],
          docArr: [{ name: { type: String, unique: true } }]
        });
    
        // Attach the plugin to the schema
        schema.plugin(arrayUniquePlugin);
        const M = mongoose.model('Test', schema);
    
        M.create({}, function(error, doc) {
          assert.ifError(error);
          doc.arr.push('test');
          doc.docArr.push({ name: 'test' });
          doc.save(function(error) {
            assert.ifError(error);
            doc.arr.push('test');
            doc.save(function(error) {
              assert.ok(error);
              // MongooseError: Duplicate values in array `arr`: [test,test]
              assert.ok(error.errors['arr'].message.indexOf('Duplicate values') !== -1,
                error.errors['arr'].message);
            });
          });
        });
      

    Why a Separate Plugin?

    In mongoose, unique is not a validator, but a shorthand for creating a unique index in MongoDB. The unique index on arr in the previous example would prevent multiple documents from having the value 'test' in arr, but would not prevent a single document from having multiple instances of the value 'test' in arr.

        const schema = new mongoose.Schema({
          arr: [{ type: String, unique: true }]
        });
    
        // Do *not* attach the plugin
        // schema.plugin(arrayUniquePlugin);
        const M = mongoose.model('Test2', schema);
    
        // Since `unique` creates an index, need to wait for the index to finish
        // building before the `unique` constraint kicks in.
        M.on('index', function(error) {
          assert.ifError(error);
          M.create({ arr: ['test'] }, function(error, doc) {
            doc.arr.push('test');
            doc.save(function(error) {
              // No error! That's because, without this plugin, a single doc can have
              // duplicate values in `arr`. However, if you tried to `save()`
              // a separate document with the value 'test' in `arr`, it will fail.
            });
          });
        });
      

    Caveat With push()

    This plugin attaches a custom validator to handle duplicate array entries. However, there is an additional edge case to handle: calling push() on an array translates into a $push in MongoDB, so if you have multiple copies of a document calling push() at the same time, the custom validator won't catch it. This plugin will surface a separate error for this case.

        const M = mongoose.model('Test');
    
        // Create a document with an empty `arr`
        M.create({}, function(error, doc) {
          assert.ifError(error);
          // Get 2 copies of the same underlying document
          M.findById(doc, function(error, doc1) {
            M.findById(doc, function(error, doc2) {
              // `push()` and `save()` on the first doc. Now `doc2` is out of date,
              // it doesn't know that `doc1` pushed 'test'.
              doc1.arr.push('test');
              doc1.save(function(error) {
                assert.ifError(error);
                doc2.arr.push('test');
                doc2.save(function(error) {
                  // Because of plugin, you'll get the below error
                  // VersionError: No matching document found for id "59192cbac4fd9871f28f4d61"
                });
              });
            });
          });
        });
      

    Keywords

    none

    Install

    npm i mongoose-unique-array

    DownloadsWeekly Downloads

    229

    Version

    0.4.2

    License

    Apache 2.0

    Unpacked Size

    34.3 kB

    Total Files

    10

    Last publish

    Collaborators

    • vkarpov15