Preventing Duplicates in your Meteor.js Collections

Using “update” to effectively keep collections clean and free from repeat data

I have frequently come across the problem of how to prevent yourself from inserting duplicates in a Meteor/MongoDB collection, for example, using a collection for configuration. Regardless of your purpose for preventing duplicates, the following is one method that I have found particularly useful.

The example that will be used will be a collection that contains various authors that a editor wants to keep. The following allows the editor to create a default group of editors every time the database is reset (this works great in packages creating a default or example data for the developer).

// File Location `server/authors.js` // To begin, we'll simply create a new `Authors` collection, either

// creating or grabbing the current MongoDB database

Authors = new Meteor.Collection(‘authors’); // Now we'll define the default set of authors

const authors = [

{

name: "John Smith",

gender: "Male",

birthday: "01/25/1984",

topics: ['SciFi','Mystery']

},

{

name: 'Jillian Mathews',

gender: "Female",

birthday: "02/03/1992",

topics: ['Romance','Historical Fiction']

},

{

name: 'Tyler Cosgrove',

gender: 'Male',

birthday: "06/09/NOPE",

topics: ['Programming Languages', 'Web Development']

}

]; // This is the nitty gritty part

// Here you'll need to use the underscore package (or create

// your own for loop to iterate through the author array) _.each(authors, function(author) {

Authors.update({name: author.name}, {$set: author}, {upsert: true});

});

Let’s break down that last part, as you should have some familiarity with creating arrays of objects as well as creating collections in Meteor.

Looking at

_.each(authors, function(author) {...}

you would hopefully recognize that this is a function provided by underscore.js. For those of you not familiar with this however, it is actually quite simple. _.each takes two arguments, the first being the array (or object) that you wish to iterate over. The second being a function containing what you want to do to each portion of the array. The function takes in an argument that each passes to it (in this case an author).

The inside of the function however is what we’ve come to look for.

Authors.update({name: author.name}, {$set: author}, {upsert: true});

That is a mouthful. Let’s break it down.

Authors.update(...);

This simply calls the update function from out Authors collection. Documentation on the update function can be found on the MongoDB website

{name: author.name}

This first argument is telling the function to search for a document (database entry) with a field name of the author’s name (so, for example on the first iteration ‘John Smith’

{$set: author}

The second argument tells the function to set the document to the value of author (which in this case is an object).

{upsert: true}

Lastly, the third argument, where all the magic takes place. By setting upsert equal to true, this argument tells the function to create a new document, if a document cannot be found matching the search (as set in the first argument). Otherwise, if an entry is found, it updates the entry.

Quick disclaimer: I would not recommend using this in a production environment. This is purely to ensure that your development environment is how you need it. In production databases “spin-ups” should be managed by hand.