34

say I have this array property ('articles') on a Mongoose schema:

articles: [ 

 {
  kind: 'bear',
  hashtag: 'foo'    
 },

 {
  kind: 'llama',
  hashtag: 'baz',
  },

 {
  kind: 'sheep',
  hashtag: 'bar',
  }

]

how can I use

$addToSet https://docs.mongodb.org/manual/reference/operator/update/addToSet/

to add to this array by checking the value of hashtag to see if it's unique?

For example, if I want to add the following object to the above array, I want Mongo to 'reject' it as a duplicate:

{
  kind: 'tortoise',
  hashtag: 'foo'

}

because hashtag=foo has already been taken.

The problem is that I only know how to use $addToSet with simple arrays of integers...

for example, if articles looked like this:

articles: [ 1 , 5 , 4, 2]

I would use $addToSet like this:

var data = {

    "$addToSet": {
     "articles": 9
   }

}

model.update(data);

but how can I accomplish the same thing with an array of objects where the unique field is a string, in this case 'hashtag'? The docs don't make this clear and it seems like I have searched everywhere..

thanks

2 Answers 2

54

You need to use the $ne operator.

var data = { 'kind': 'tortoise', 'hashtag': 'foo' };
Model.update(
    { 'articles.hashtag': { '$ne': 'foo' } }, 
    { '$addToSet': { 'articles': data } }
)

This will update the document only if there is no sub document in the "article" array with the value of hashtag equals to "foo".

As @BlakesSeven mentioned in the comment

The $addToSet becomes irrelevant once you are testing for the presence of one of the values, so this may as well be a $push for code clarity. But the principle is correct since $addToSet works on the whole object and not just part of it.

Model.update({ 
    { 'articles.hashtag': { '$ne': 'foo' } }, 
    { '$push': {'articles':  data } }
)
Sign up to request clarification or add additional context in comments.

8 Comments

What if the object contains "_id" field? Will it still require '$ne' operator to check duplicity?
@styvane What if instead of matching with only hashtag I want to match with "article.kind" and "article.hashtg" and then add to set if the perfect match not exist
@PavanVora, you could you {'articles.hastag': {'$ne': 'cats'}, 'articles.kind': {'$ne': 'struct'}} in the filter.
@PavanVora If you're looking for perfect matches you could simply use $addToSet itself
@PavanVora Yes, it'll work.. Only thing is, the order of keys within the object should be the same... So {a, b, c} and {a, c, b} are treated as different objects even though its basically the same object
|
0
// add the comment's id to the commentsList : 
                        // share.comments.commentsList.addToSet(callback._id);
                        share.update(
                            { '$push': {'comments.commentsList':  mongoose.Types.ObjectId(callback._id) } }
                        , function(){
                            console.log('added comment id to the commentsList array of obectIds')
                        })

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.