Yábir Garcia
Yábir Garcia

Reputation: 339

Duplicated items using mongoose

I'm trying to insert elements from a list in my database using node and mongoose. The list contains just url as strings. Before inserting it checks if the url is already in the database for a user. "person" is a document and links is an array:

for (var i = 0; i < url.length; i++) {
          var found = false;
          //if no links
          if (person.links.length === 0) {
            person.links.push({link: url[i]});
            person.save(function (err) {
              if (err) return handleError(err);
            });
          }
          else{
            //for each link in database
            for (var z = 0; z < person.links.length; z++) {
              //If we find it change status
              if (url[i] === person.links[z].link) {
                found = true;
                break;
              }
            }
            //If we have not found it
            if (found === false)
            {
              //Save it
              person.links.push({link: url[i]});
              person.save(function (err) {
                if (err) return handleError(err);
              });
            }
          }

But it generates duplicate elemts and I don't understand why:

"links" : [
        {
            "link" : "google.es",
            "_id" : ObjectId("57d15ed8b9859615ef11e8b6"),
        },
        {
            "link" : "gog.com",
            "_id" : ObjectId("57d15ed8b9859615ef11e8b7"),
        },
        {
            "link" : "google.es",
            "_id" : ObjectId("57d15ed8b9859615ef11e8b6"),
        },
        {
            "link" : "gog.com",
            "_id" : ObjectId("57d15ed8b9859615ef11e8b7"),
        }
    ],

Furthermore the _id is repeated for the same url so I don't know if it is my fault or that something is not working right.

Upvotes: 1

Views: 499

Answers (1)

chridam
chridam

Reputation: 103475

The array operator $addToSet is competent to the task enough. It adds a value to an array unless the value is already present, in which case $addToSet does nothing to that array.

The only task you have to do is preprocess the url array into an array of documents similar to the links embedded schema in Person. Use map() to tranform the array.

Consider the following operation which exactly the same thing albeit more efficiently:

var links = url.map(function(u){ return { "link": u }; });
person.update(
    { "_id": personId },
    { "$addToSet": { "links": { "$each": links } } },
    function(err, result) {
        if (err) return handleError(err);
        console.log(result);
    }
);

or just use the Mongoose's addToSet() method:

var links = url.map(function(u){ return { "link": u }; });
console.log(person.links)

// call the addToSet function using the array with apply()
var added = person.links.addToSet.apply(this, links);

console.log(person.links);
console.log(added);

Upvotes: 3

Related Questions