0

I am trying to save a unique array of String elements using MongoDB but for some reason it allows me to save duplicates.

I am using mongoose. My code:

 schema = mongoose.Schema({
    "searchingId": { "type":  String,
        "unique": true,
        "index": true },
    "sharedTo" : {
        type: [String],
        unique: true,
        "trim":true
    }
}, {collection: 'myCollection'});

Basically the point is to keep a list of email addresses where the user had sent emails and to prevent the user from spamming them. But this schema will allow me to push any string to a sharedTo array and to .save() it no matter whether the duplicates exist. How to prevent this from happening?

EDIT: Lahar's answer does help with my question but not entierly. I would like to prevent user from adding emails if there is at least one duplicate. So basically $addToSet will help with uniqueness but not with my question.

1
  • Can you give examples of the kind of duplicate records you're trying to prevent, which it is allowing? Commented May 15, 2016 at 21:57

3 Answers 3

1

You can use $addToSet instead of $push to add email in "sharedTo" array. That won't add duplicate element(email in your case).

By providing unique:true to whole array field won't check uniqueness of array element.

Please check $addToSet documentation.

Sign up to request clarification or add additional context in comments.

4 Comments

This is almost the answer I need. The problem is that I want to throw an error if there is a duplicate and to return 409 conflict. Is that even possible?
So when you run that update it returns writeResult object with count nMatched, nUpserted, nModified. nModified will tell you how many documents are modified.
Yes but it saves the object to the database, so technically i would have to rollback to previous version if the modified is less than length of input? That sounds like dirty and wrong solution, doesn't it?
Can you provide the code snippet where you need to validate ? That will give better idea where and how you actually want.
0

you can implement your own static function that will run from the schema class to do this for every email entered

UserSchema.statics.findUseremail = function(useremail, suffix,
callback) {

var _this = this;
var possibleuseremail = useremail + (suffix || '');
_this.findOne({
    useremail: possibleuseremail
    }, function(err, userem) {
    if (!err) {
        if (!userem) {
            callback(findUseremail);
        } else {
        return _this.findUseremail(useremail, (suffix || 0) +
        1, callback);
        }
    } else {
    callback(null);
    }
});
};

Comments

0

So looks like I had found the solution myself but thanks to the Lahar Shah answer for pointing me in the right direction. Instead of using

Model.update(conditions, doc, [options], [callback])

I did

  • fetching the object
  • Added each of emails to my sharedTo attribute while checking for duplicates.
  • saving the object if no duplicates

Code:

var  length = emails.length;
for( var i = 0; i < length; i++ ) {
    var saved = doc.sharedTo.addToSet(emails[i]).length;
    if (saved != 1) {
        //status 409 - You have already sent email to user emails[i]
        return;
    }
}

doc[0].save(function(fail, success) {
    if(fail) {
        //error
    } else {
        //success return 200
    }
});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.