Reputation: 339
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
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