Node.js Basics — MongoDB Complex Updates and Upserts

John Au-Yeung - Jan 24 '21 - - Dev Community

Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62

Subscribe to my email list now at http://jauyeung.net/subscribe/

Node.js is a popular runtime platform to create programs that run on it.

It lets us run JavaScript outside the browser.

In this article, we’ll look at how to start using Node.js to create programs.

Filtered Positional Operator for Arrays in Documents

We can get the position and insert what we want into it.

For example, we can write:

const { MongoClient } = require('mongodb');
const connection = "mongodb://localhost:27017";
const client = new MongoClient(connection);

async function run() {
  try {
    await client.connect();
    const testCollection = await client.db("test").collection('test');
    const result = await testCollection.insertOne({
      name: "Popeye",
      address: "1 Sweethaven",
      items: [
        {
          type: "pizza",
          size: "large",
          toppings: ["garlic, spinach"],
        },
        {
          type: "calzone",
          toppings: ["ham"],
        },
      ],
    });
    console.log(result)
    const query = { name: "Popeye" };
    const options = {
      arrayFilters: [{
        "orderItem.type": "pizza",
        "orderItem.size": "large",
      }]
    };
    const updateDocument = {
      $push: { "items.$[orderItem].toppings": "veggie" }
    };
    const updateResult = await testCollection.updateOne(query, updateDocument, options);
    console.log(updateResult)
  } finally {
    await client.close();
  }
}
run().catch(console.dir);
Enter fullscreen mode Exit fullscreen mode

We add the items into the toppings array of the object with the given type and size in the items array.

The items.$[orderItem].toppings gets the item with the given result from the arrayFilters search.

It’ll search the items array for the entry by replacing orderItem with the index of the search result in arrayFilters .

Now we should see veggie as the 2nd wntr of the toppings array property.

The document should now be:

{
   "_id":{
      "$oid":"5f68f03c9b873d2818970b52"
   },
   "name":"Popeye",
   "address":"1 Sweethaven",
   "items":[
      {
         "type":"pizza",
         "size":"large",
         "toppings":[
            "garlic, spinach",
            "veggie"
         ]
      },
      {
         "type":"calzone",
         "toppings":[
            "ham"
         ]
      }
   ]
}
Enter fullscreen mode Exit fullscreen mode

Upsert

We can upsert one or more documents with the updateOne , replaceOne or updateMany methods.

To update a single entry, we can use the updateOne method:

const { MongoClient } = require('mongodb');
const connection = "mongodb://localhost:27017";
const client = new MongoClient(connection);

async function run() {
  try {
    await client.connect();
    const testCollection = await client.db("test").collection('test');
    const result = await testCollection.insertOne({
      name: "Popeye",
    });
    console.log(result)
    const query = { name: "Popeye" };
    const update = { $set: { name: "Popeye", address: "3 Nassau St" } };
    const options = {};
    const updateResult = await testCollection.updateOne(query, update, options);
    console.log(updateResult)
  } finally {
    await client.close();
  }
}
run().catch(console.dir);
Enter fullscreen mode Exit fullscreen mode

We insert an item with a name key.

Then we call the updateOne with the query object to find the item with the given name value.

Then we create the update object with the $set property to update the properties with the items.

The replaceOne method lets us replace an item with another one.

For example, we can write:

const { MongoClient } = require('mongodb');
const connection = "mongodb://localhost:27017";
const client = new MongoClient(connection);

async function run() {
  try {
    await client.connect();
    const testCollection = await client.db("test").collection('test');
    const result = await testCollection.insertOne({
      name: "Popeye",
    });
    console.log(result)
    const query = { name: "Popeye" };
    const update = { name: "Popeye", address: "3 Nassau St" };
    const options = {};
    const updateResult = await testCollection.replaceOne(query, update, options);
    console.log(updateResult)
  } finally {
    await client.close();
  }
}
run().catch(console.dir);
Enter fullscreen mode Exit fullscreen mode

We call replaceOne to replace the item with name set to 'Popeye' to an object with both the name and address properties.

Conclusion

We can call various methods to update our MongoDB documents.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .