Quick Start: Node.js & MongoDB - How to Create Documents

Lauren Schaefer

#Node
Quick Start Node.js and MongoDB

In the first post in this series, I walked you through how to connect to a MongoDB database from a Node.js script, retrieve a list of databases, and print the results to your console. If you haven’t read that post yet, I recommend you do so and then return here.

Now that we have connected to a database, let’s kick things off with the first of the CRUD operations: create.


Get started with an M0 cluster on Atlas today. It's free forever, and it’s the easiest way to try out the steps in this blog series.

Documents and Collections

MongoDB stores data in BSON documents. BSON is a binary representation of JSON (JavaScript Object Notation) documents. When you read MongoDB documentation, you’ll frequently see the term “document,” but you can think of a document as simply a JavaScript object. For those coming from the SQL world, you can think of a document as being roughly equivalent to a row.

MongoDB stores groups of documents in collections. For those with a SQL background, you can think of a collection as being roughly equivalent to a table.

Every document is required to have a field named _id. The value of _id must be unique for each document in a collection, is immutable, and can be of any type other than an array. MongoDB will automatically create an index on _id. You can choose to make the value of _id meaningful (rather than a somewhat random ObjectId) if you have a unique value for each document that you’d like to be able to quickly search.

In this blog series, we’ll use the sample Airbnb listings dataset. The sample_airbnb database contains one collection: listingsAndReviews. This collection contains documents about Airbnb listings and their reviews.

Let’s take a look at a document in the listingsAndReviews collection. Below is part of an Extended JSON representation of a BSON document:

{
"_id":"10057447",
"listing_url":"https://www.airbnb.com/rooms/10057447",
"name":"Modern Spacious 1 Bedroom Loft",
"summary":"Prime location, amazing lighting and no annoying neighbours.  Good place to rent if you want a relaxing time in Montreal.",
"property_type":"Apartment",
"bedrooms":{"$numberInt":"1"},
"bathrooms":{"$numberDecimal":"1.0"},
"amenities":["Internet","Wifi","Kitchen","Heating","Family/kid friendly","Washer","Dryer","Smoke detector","First aid kit","Safety card","Fire extinguisher","Essentials","Shampoo","24-hour check-in","Hangers","Iron","Laptop friendly workspace"],
}

Create a Listing

Let’s begin by creating a new Airbnb listing. We can do so by calling Collection’s insertOne(). insertOne() will insert a single document into the collection. The only required parameter is the new document (of type object) that will be inserted. If our new document does not contain the _id field, the MongoDB driver will automatically create an id for the document.

Our function to create a new listing will look something like the following:

async function createListing(client, newListing){
    const result = await client.db("sample_airbnb").collection("listingsAndReviews").insertOne(newListing);
    console.log(`New listing created with the following id: ${result.insertedId}`);
}

We can call this function by passing a connected MongoClient as well as an object that contains information about a listing.

await createListing(client,
            {
                name: "Lovely Loft",
                summary: "A charming loft in Paris",
                bedrooms: 1,
                bathrooms: 1
            }
        );

The output would be something like the following:

New listing created with the following id: 5d9ddadee415264e135ccec8

Note that since we did not include a field named _id in the document, the MongoDB driver automatically created an _id for us. The _id of the document you create will be different from the one shown above. For more information on how MongoDB generates _id, see the official documentation.

Create Many Listings

Sometimes you will want to insert more than one document at a time. You could choose to repeatedly call insertOne(). The problem is that, depending on how you’ve structured your code, you may end up waiting for each insert operation to return before beginning the next, resulting in slow code.

Instead, you can choose to call Collection’s insertMany(). insertMany() will insert an array of documents into your collection.

One important option to note for insertMany() is ordered. If ordered is set to true, the documents will be inserted in the order given in the array. If any of the inserts fail (for example, if you attempt to insert a document with an _id that is already being used by another document in the collection), the remaining documents will not be inserted. If ordered is set to false, the documents may not be inserted in the order given in the array. MongoDB will attempt to insert all of the documents in the given array--regardless of whether any of the other inserts fail. By default, ordered is set to true.

Let’s write a function to create multiple Airbnb listings.

async function createMultipleListings(client, newListings){
    const result = await client.db("sample_airbnb").collection("listingsAndReviews").insertMany(newListings);
 
    console.log(`${result.insertedCount} new listing(s) created with the following id(s):`);
    console.log(result.insertedIds);
 
}

We can call this function by passing a connected MongoClient and an array of objects that contain information about listings.

   await createMultipleListings(client, [
      {
           name: "Infinite Views",
           summary: "Modern home with infinite views from the infinity pool",
           property_type: "House",
           bedrooms: 5,
           bathrooms: 4.5,
           beds: 5
       },
       {
           name: "Private room in London",
           property_type: "Apartment",
           bedrooms: 1,
           bathroom: 1
       },
       {
           name: "Beautiful Beach House",
           summary: "Enjoy relaxed beach living in this house with a private beach",
           bedrooms: 4,
           bathrooms: 2.5,
           beds: 7,
           last_review: new Date()
       }
   ]);

Note that every document does not have the same fields, which is perfectly OK. (I’m guessing that those who come from the SQL world will find this incredibly uncomfortable, but it really will be OK :-) ). When you use MongoDB, you get a lot of flexibility in how to structure your documents. If you later decide you want to add schema validation rules so you can guarantee your documents have a particular structure, you can.

The output of calling createMultipleListings() would be something like the following:

3 new listing(s) created with the following id(s):
{ '0': 5d9ddadee415264e135ccec9,
  '1': 5d9ddadee415264e135cceca,
  '2': 5d9ddadee415264e135ccecb }

Just like the MongoDB Driver automatically created the _id field for us when we called insertOne(), the Driver has once again created the _id field for us when we called insertMany().

Wrapping Up

This post included many code snippets that built on code from a previous post. To get a full copy of the code used in today’s post, visit the Node.js Quick Start GitHub Repo.

Be on the lookout for the next post in this series where we’ll work through the next of the CRUD operations: read.

Series versions

The examples in this article were created with the following application versions:

ComponentVersion used
MongoDB4.0
MongoDB Node.js Driver3.3.2
Node.js10.16.3

All posts in the Quick Start: Node.js and MongoDB series: