Navigation

Update Documents in MongoDB

Overview

The code snippets on this page demonstrate how to update documents that are stored in a MongoDB collection. Update operations use query filters to specify which documents to update and update operators to describe the changes to apply to matching documents.

This page also covers several different update operators that you can use to update fields or update array values.

Data Model

The examples on this page use a collection named store.items that models various items available for purchase in an online store. Each item has a name, an inventory quantity, and an array of customer reviews.

// store.items
{
    _id:      <ObjectID>,
    name:     <string>,
    quantity: <int>,
    reviews:  [ { username: <string>, comment: <string> } ]
}

Snippet Setup

To use a code snippet in a function, you must first instantiate a MongoDB collection handle:

exports = function() {
  const mongodb = context.services.get("mongodb-atlas");
  const itemsCollection = mongodb.db("store").collection("items");
  const purchasesCollection = mongodb.db("store").collection("purchases");
}

To use a code snippet in a JavaScript project, you must first do the following:

1

Import Stitch Dependencies

Import from CDN
<!-- Import the Stitch JS SDK at the top of the file -->
<script src="https://s3.amazonaws.com/stitch-sdks/js/bundles/4/stitch.js"></script>
<script>
  // Destructure Stitch JS SDK Components
  const { Stitch, RemoteMongoClient, BSON } = stitch;
</script>

– or –

Import from Module
// Import components of the Stitch JS SDK at the top of the file
import {
  Stitch,
  RemoteMongoClient,
  BSON
} from "mongodb-stitch-browser-sdk";
2

Instantiate a MongoDB Remote Collection Handle

const stitchApp = Stitch.initializeDefaultAppClient("<Your App ID>");
const mongodb = stitchApp.getServiceClient(RemoteMongoClient.factory, "mongodb-atlas");
const itemsCollection = mongodb.db("store").collection("items");
const purchasesCollection = mongodb.db("store").collection("purchases");

To use a code snippet in an Android project, you must first do the following:

1

Set Up Your Project

Follow the steps in the Set up a MongoDB Mobile Project guide.

Note

For more details on setting up your Android app to use Stitch, refer to Build a Mobile App with Sync or Build a Local-Only Mobile App.

2

Import Stitch Dependencies

For CRUD operations on a remote MongoDB collection, you will use one or more of the following import statements:

// Base Stitch Packages
import com.mongodb.stitch.android.core.Stitch;
import com.mongodb.stitch.android.core.StitchAppClient;
// Stitch Authentication Packages
import com.mongodb.stitch.android.core.auth.StitchUser;
import com.mongodb.stitch.core.auth.providers.anonymous.AnonymousCredential;
// MongoDB Service Packages
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoCollection;
// Utility Packages
import com.mongodb.stitch.core.internal.common.BsonUtils;

To Sync documents between a remote and a local MongoDB instance, you will also need to import the following packages:

// Stitch Sync Packages
import com.mongodb.stitch.core.services.mongodb.remote.sync.ChangeEventListener;
import com.mongodb.stitch.core.services.mongodb.remote.sync.DefaultSyncConflictResolvers;
import com.mongodb.stitch.core.services.mongodb.remote.sync.ErrorListener;
import com.mongodb.stitch.core.services.mongodb.remote.sync.internal.ChangeEvent;

Important

If you use Sync, be sure to add .sync() before every remote database call in the examples below, as in the following:

itemsCollections.sync().find()

To perform CRUD operations only on the local (on-device) database, import the following packages:

// MongoDB Mobile Local Database Packages
import com.mongodb.stitch.android.services.mongodb.local.LocalMongoDbService;
3

Instantiate a MongoDB Collection Handle

Top of Activity File
private StitchAppClient stitchClient;
private RemoteMongoClient mongoClient;
private RemoteMongoCollection itemsCollection;
In Activity.onCreate()
stitchClient = Stitch.getDefaultAppClient();
mongoClient = stitchClient.getServiceClient(RemoteMongoClient.factory, "mongodb-atlas");
itemsCollection = mongoClient.getDatabase("store").getCollection("items");
purchasesCollection = mongoClient.getDatabase("store").getCollection("purchases");

To use a code snippet in an iOS project, you must first do the following:

1

Set Up Your Project

Follow the steps in the Set up a MongoDB Mobile Project guide.

2

Import Stitch Dependencies

In scope (e.g. UIViewController)
import StitchCore
import StitchCoreRemoteMongoDBService
import StitchRemoteMongoDBService
3

Initialize the MongoDB Stitch iOS SDK

Application Startup (e.g. AppDelegate.didFinishLaunchingWithOptions())
do {
    let _ = try Stitch.initializeDefaultAppClient(
        withClientAppID: "YOUR-APP-ID"
    )
} catch {
    print("Failed to initialize MongoDB Stitch iOS SDK: \(error)")
}
4

Instantiate a MongoDB Collection Handle

In scope (e.g. UIViewController)
// Variables in scope:
private lazy var stitchClient = Stitch.defaultAppClient!
private var mongoClient: RemoteMongoClient?
private var itemsCollection: RemoteMongoCollection<Document>?

// Set the stitch variables declared above in viewDidLoad()
mongoClient = stitchClient.serviceClient(
    fromFactory: remoteMongoClientFactory,
    withName: "mongodb-atlas"
)
itemsCollection = mongoClient?.db("store").collection("items")
purchasesCollection = mongoClient?.db("store").collection("purchases")

Methods

Update a Single Document

You can update a single document using the collection.updateOne() action.

The following snippet updates the name of a single document in the items collection from legos to blocks and adds a price of 20.99:

const query = { name: "legos" };
const update =
  $set: {
    name: "blocks",
    price: 20.99,
    category: "toys"
  }
};
const options = { upsert: false };

itemsCollection.updateOne(query, update, options)
  .then(result => {
    const { matchedCount, modifiedCount } = result;
    if(matchedCount && modifiedCount) {
      console.log(`Successfully updated the item.`)
    }
  })
  .catch(err => console.error(`Failed to update the item: ${err}`))
const query = { name: "legos" };
const update =
  $set: {
    name: "blocks",
    price: 20.99,
    category: "toys"
  }
};
const options = { upsert: false };

itemsCollection.updateOne(query, update, options)
  .then(result => {
    const { matchedCount, modifiedCount } = result;
    if(matchedCount && modifiedCount) {
      console.log(`Successfully updated the item.`)
    }
  })
  .catch(err => console.error(`Failed to update the item: ${err}`))
Document filterDoc = new Document().append("name", "legos");
Document updateDoc = new Document().append("$set",
    new Document()
    .append("name", "blocks")
    .append("price", 20.99)
    .append("category", "toys")
);

final Task<RemoteUpdateResult> updateTask =
    itemsCollection.updateOne(filterDoc, updateDoc);
updateTask.addOnCompleteListener(new OnCompleteListener <RemoteUpdateResult> () {
    @Override
    public void onComplete(@NonNull Task <RemoteUpdateResult> task) {
        if (task.isSuccessful()) {
            long numMatched = task.getResult().getMatchedCount();
            long numModified = task.getResult().getModifiedCount();
            Log.d("app", String.format("successfully matched %d and modified %d documents",
                    numMatched, numModified));
        } else {
            Log.e("app", "failed to update document with: ", task.getException());
        }
    }
});
let query : Document = ["name": "legos"];
let update : Document = [
    "$set": [
        "name": "blocks",
        "price": 20.99
    ] as Document
];
let options = RemoteUpdateOptions(upsert: false);

itemsCollection?.updateOne(filter: query, update: update) { result in
    switch result {
    case .success(let result):
        if result.matchedCount && result.modifiedCount {
            print("Successfully added a new review.")
        } else {
            print("Could not find a matching item.")
        }
    case .failure(let error):
        print("Failed to update: \(error)");
    }
}

Update One or More Documents

You can update a single document using the collection.updateMany() action.

The following snippet updates all documents in the items collection by multiplying their quantity values by 10:

const query = {};
const update = { $mul: { quantity: 10 } };
const options = { upsert: false }

return itemsCollection.updateMany(query, update, options)
  .then(result => {
    const { matchedCount, modifiedCount } = result;
    console.log(`Successfully matched ${matchedCount} and modified ${modifiedCount} items.`)
    return result
  })
  .catch(err => console.error(`Failed to update items: ${err}`))
const query = {};
const update = { $mul: { quantity: 10 } };
const options = { upsert: false }

itemsCollection.updateMany(query, update, options)
  .then(result => {
    const { matchedCount, modifiedCount } = result;
    console.log(`Successfully matched ${matchedCount} and modified ${modifiedCount} items.`)
  })
  .catch(err => console.error(`Failed to update items: ${err}`))
Document filterDoc = new Document();
Document updateDoc = new Document().append("$mul", new Document().append("quantity", 10));

final Task <RemoteUpdateResult> updateTask =
  itemsCollection.updateMany(filterDoc, updateDoc);
updateTask.addOnCompleteListener(new OnCompleteListener <RemoteUpdateResult> () {
    @Override
    public void onComplete(@NonNull Task <RemoteUpdateResult> task) {
        if (task.isSuccessful()) {
            long numMatched = task.getResult().getMatchedCount();
            long numModified = task.getResult().getModifiedCount();
            Log.d("app", String.format("successfully matched %d and modified %d documents",
                  numMatched, numModified));
        } else {
            Log.e("app", "failed to update document with: ", task.getException());
        }
    }
});
let query : Document = [];
let update : Document = ["$mul": ["quantity": 10] as Document];

itemsCollection?.updateMany(filter: query, update: update) { result in
    switch result {
    case .success(let result):
        print("Successfully matched \(result.matchedCount) and modified \(result.modifiedCount) items.");
    case .failure(let error):
        print("Failed to modify items: \(error)");
    }
}

Options

Upsert Documents

If an update operation does not match any document in the collection, you can automatically insert a single new document into the collection that matches the update query by setting the upsert option to true.

The following snippet updates a document in the items collection that has a name of board game by incrementing its quantity by 5. The upsert option is enabled, so if no document has a name value of "board game" then MongoDB inserts a new document with the name field set to "board game" and the quantity value set to 5:

const query = { name: "board games" };
const update = { $inc: { quantity: 5 } };
const options = { upsert: true }

itemsCollection.updateOne(query, update, options)
  .then(result => {
    const { matchedCount, modifiedCount, upsertedId } = result;
    if(upsertedId) {
      console.log(`Document not found. Inserted a new document with _id: ${upsertedId}`)
    } else {
      console.log(`Successfully increased ${query.name} quantity by ${update.$inc.quantity}`)
    }
  })
  .catch(err => console.error(`Failed to upsert document: ${err}`))
const query = { name: "board games" };
const update = { $inc: { quantity: 5 } };
const options = { upsert: true }

itemsCollection.updateOne(query, update, options)
  .then(result => {
    const { matchedCount, modifiedCount, upsertedId } = result;
    if(upsertedId) {
      console.log(`Document not found. Inserted a new document with _id: ${upsertedId}`)
    } else {
      console.log(`Successfully increased ${query.name} quantity by ${update.$inc.quantity}`)
    }
  })
  .catch(err => console.error(`Failed to upsert document: ${err}`))
Document filterDoc = new Document("name", "board game");
Document updateDoc = new Document("$inc", new Document("quantity", 5));
RemoteUpdateOptions options = new RemoteUpdateOptions().upsert(true);

final Task <RemoteUpdateResult> updateTask =
  itemsCollection.updateOne(filterDoc, updateDoc, options);
updateTask.addOnCompleteListener(new OnCompleteListener <RemoteUpdateResult> () {
    @Override
    public void onComplete(@NonNull Task <RemoteUpdateResult> task) {
        if (task.isSuccessful()) {
            if (task.getResult().getUpsertedId() != null) {
                String upsertedId = task.getResult().getUpsertedId().toString();
                Log.d("app", String.format("successfully upserted document with id: %s",
                  upsertedId));
            } else {
                long numMatched = task.getResult().getMatchedCount();
                long numModified = task.getResult().getModifiedCount();
                Log.d("app", String.format("successfully matched %d and modified %d documents",
                      numMatched, numModified));
            }
        } else {
            Log.e("app", "failed to update document with: ", task.getException());
        }
    }
});
 let query : Document = ["name": "board game"];
 let update : Document = ["$inc": ["quantity": 5] as Document];
 let options = RemoteUpdateOptions(upsert: true);

 itemsCollection?.updateOne(filter: query, update: update, options: options) { result in
     switch result {
     case .success(let result):
         if let upsertedId = result.upsertedId {
             print("Document not found. Inserted a new document with _id: \(upsertedId).")
         } else {
             print("Successfully increased \(query.name) quantity by \(update["$inc"].quantity)")
         }
     case .failure(let error):
         print("Failed to upsert: \(error)");
     }
 }

Field Update Operators

Set the Value of a Field

You can use the $set operator to set the value of a single field without affecting other fields in a document.

{ "$set": { "<Field Name>": <Value>, ... } }

Rename a Field

You can use the $rename operator to change the name of a single field in a document.

{ "$rename": { "<Current Field Name>": <New Field Name>, ... } }

Incremement a Value

You can use the $inc operator to add a specified number to the current value of a field. The number can be positive or negative.

{ "$inc": { "<Field Name>": <Increment Number>, ... } }

Multiply a Value

You can use the $mul operator to multiply a specified number with the current value of a field. The number can be positive or negative.

{ "$mul": { "<Field Name>": <Multiple Number>, ... } }

Array Update Operators

Push an Element Into an Array

You can use the $push operator to add a value to the end of an array field.

{ "$push": { "<Array Field Name>": <New Array Element>, ... } }

Pop the Last Element out of an Array

You can use the $pop operator to remove either the first or last element of an array field. Specify -1 to remove the first element and 1 to remove the last element.

{ "$pop": { "<Array Field Name>": <-1 | 1>, ... } }

Add a Unique Element to an Array

You can use the $addToSet operator to add a value to an array field if that value is not already included in the array. If the value is already present, $addToSet does nothing.

{ "$addToSet": { "<Array Field Name>": <Potentially Unique Value>, ... } }

Remove Elements from an Array

You can use the $pull operator to remove all instances of any values that match a specified condition from an array field.

{ "$pull": { "<Array Field Name>": <Value | Expression>, ... } }