Navigation

Find Documents in MongoDB

Overview

The code snippets on this page demonstrate how to read documents that are stored in a MongoDB collection. Read operations use query filters to specify which documents to return from the database. This page also covers several different query patterns that you can use in query filters to precisely match documents.

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

Find a Single Document

You can find a single document using the collection.findOne() action.

Note

The collection.findOne() action is currently only available in Functions. You can emulate findOne behavior in a Client SDK by calling collection.find() with a limit of 1.

The following snippet finds a single document from the items collection that has a quantity greater than or equal to 25:

const query = { "quantity": { "$gte": 25 } };
const projection = {
 "title": 1,
 "quantity": 1,
}

return itemsCollection.findOne(query, projection)
  .then(result => {
    if(result) {
      console.log(`Successfully found document: ${result}.`);
    } else {
      console.log("No document matches the provided query.");
    }
    return result;
  })
  .catch(err => console.error(`Failed to find document: ${err}`));
const query = { "quantity": { "$gte": 25 } };
const options = {
  "projection": {
    "title": 1,
    "quantity": 1,
  },
  "sort": { "title": -1 },
};
itemsCollection.findOne(query, options)
  .then((result) => {
    if (result) {
      console.log(`Successfully found document: ${result}.`);
    } else {
      console.log('No document matches the provided query.');
    }
  })
  .catch((err) => console.error(`Failed to find document: ${err}`));
Document query = new Document().append("quantity",
    new Document().append("$gte", 20));

Document projection = new Document()
    .append("_id", 1)
    .append("quantity", 1);
Document sort = new Document()
    .append("quantity", -1);

RemoteFindOptions options = new RemoteFindOptions()
    .sort(sort)
    .projection(projection);

final Task <Document> findOneAndUpdateTask = itemsCollection.findOne(query, options);
findOneAndUpdateTask.addOnCompleteListener(new OnCompleteListener <Document> () {
    @Override
    public void onComplete(@NonNull Task <Document> task) {
        if (task.getResult() == null) {
            Log.d("app", String.format("No document matches the provided query"));
        }
        else if (task.isSuccessful()) {
            Log.d("app", String.format("Successfully found document: %s",
                task.getResult()));
        } else {
            Log.e("app", "Failed to findOne: ", task.getException());
        }
    }
});
let query: Document = ["quantity": [ "$gte": 20 ] as Document]
let sort: Document = ["quantity": -1]
itemsCollection?.findOne(query, options: RemoteFindOptions.init(sort: sort)) { doc in
    switch doc {
    case .success(let doc):
        switch doc {
        case .none:
            print("No document matches the provided query")
        case .some(let doc):
            print("Successfully found document: \(doc)")
        }
    case .failure(let err):
        print("Failed to findOne: \(err)")
    }

Find One or More Documents

You can find multiple documents using the collection.find() action.

The following snippet finds all documents in the items collection that have at least one review and returns them sorted by name with the _id field omitted:

const query = { "reviews.0": { "$exists": true } };
const projection = { "_id": 0 };

return itemsCollection.find(query, projection)
  .sort({ name: 1 })
  .toArray()
  .then(items => {
    console.log(`Successfully found ${items.length} documents.`)
    items.forEach(console.log)
    return items
  })
  .catch(err => console.error(`Failed to find documents: ${err}`))
const query = { "reviews.0": { "$exists": true } };
const options = {
  "projection": { "_id": 0 },
  "sort": { "name": 1 }
};

itemsCollection.find(query, options).toArray()
  .then(items => {
    console.log(`Successfully found ${items.length} documents.`)
    items.forEach(console.log)
    return items
  })
  .catch(err => console.error(`Failed to find documents: ${err}`))
Document filterDoc = new Document()
    .append("reviews.0", new Document().append("$exists", true));

RemoteFindIterable findResults = itemsCollection
    .find(filterDoc)
    .projection(new Document().append("_id", 0))
    .sort(new Document().append("name", 1));

// One way to iterate through
findResults.forEach(item -> {
    Log.d("app", String.format("successfully found:  %s", item.toString()));
});

// Another way to iterate through
Task <List<Document>> itemsTask = findResults.into(new ArrayList<Document>());
itemsTask.addOnCompleteListener(new OnCompleteListener <List<Document>> () {
    @Override
    public void onComplete(@NonNull Task<List<Document>> task) {
        if (task.isSuccessful()) {
            List<Document> items = task.getResult();
            Log.d("app", String.format("successfully found %d documents", items.size()));
            for (Document item: items) {
                Log.d("app", String.format("successfully found:  %s", item.toString()));
            }
        } else {
            Log.e("app", "failed to find documents with: ", task.getException());
        }
    }
});
let query : Document = ["reviews.0": ["$exists": true] as Document];
let options = RemoteFindOptions(
    projection: ["_id": 0],
    sort: ["name": 1]
);

itemsCollection?.find(query, options: options).toArray({ results in
    switch results {
    case .success(let results):
        print("Successfully found \(results.count) documents: ");
        results.forEach({item in
            print(item);
        })
    case .failure(let error):
        print("Failed to find documents: \(error)");
    }
})

Count Documents in the Collection

You can count documents in a collection using the collection.count() action. You can specify a query filter to specify which documents to count. If you don’t specify a query, the action counts all documents in the collection.

The following snippet counts the number of documents in the items collection that have at least one review:

return itemsCollection.count({ "reviews.0": { "$exists": true } })
  .then(numDocs => console.log(`${numDocs} items have a review.`))
  .catch(err => console.error("Failed to count documents: ", err))
itemsCollection.count({ "reviews.0": { "$exists": true } })
  .then(numDocs => console.log(`${numDocs} items have a review.`))
  .catch(err => console.error("Failed to count documents: ", err))
Document query = new Document("reviews.0", new Document("$exists", true));

itemsCollection.count(query).addOnCompleteListener(new OnCompleteListener <Long> () {
    @Override
    public void onComplete(@NonNull Task <Long> task) {
        if (task.isSuccessful()) {
            Long numDocs = task.getResult();
            Log.d("app", String.format("%s items have a review.", numDocs.toString()));
        } else {
            Log.e("app", "Failed to count documents with exception: ", task.getException());
        }
    }
});
let query : Document = ["reviews.0": ["$exists": true] as Document];

itemsCollection?.count(query) { result in
  switch result {
  case .success(let numDocs):
    print("\(numDocs) items have a review.")
  case .failure(let error):
    print("Failed to count documents: ", error)
  }
}

Query Patterns

Query Based on a Document’s ID

You can query a collection to find a document that has a specified ID. MongoDB automatically stores each document’s ID as an ObjectId value in the document’s _id field.

{ "_id": <ObjectId> }

Example

The following query matches a document in the collection that has an _id value of 5ad84b81b8b998278f773c1b:

{ "_id": BSON.ObjectId("5ad84b81b8b998278f773c1b") }

Query Based on a Date

You can query a collection to find documents that have a field with a specific date value, or query for a documents within a range of dates.

{ "<Date Field Name>": <Date | Expression> }

Example

The following query matches documents in the collection that have a createdAt date of January 23, 2019:

{ "createdAt": new Date("01/23/2019") }

Example

The following query matches documents in the collection that have a createdAt date some time in the year 2019:

{
  "createdAt": {
    "$gte": new Date("01/01/2019"),
    "$lt": new Date("01/01/2020")
  }
}

Query Based on a Root-Level Field

You can query a collection based on the value of a root-level field in each document. You can specify either a specific value or a nested expression that MongoDB evaluates for each document.

For more information, see the Query Documents tutorial in the MongoDB Server Manual.

{ "<Field Name>": <Value | Expression> }

Example

The following query matches documents where the name field has a value of Basketball:

{ "name": "Basketball" }

Query Based on Multiple Fields

You can specify multiple query conditions in a single query document. Each root-level field of a query document maps to a field in the collection. MongoDB only returns documents that fulfill all query conditions.

For more information, see the Query on Embedded/Nested Documents tutorial in the MongoDB Server Manual.

{
  "<Field Name 1>": <Value | Expression>,
  "<Field Name 2>": <Value | Expression>
}

Example

The following query matches documents where the name field has a value of Basketball and the quantity value is greater than zero:

{
  "name": "Basketball",
  "quantity": { "$gt": 0 }
}

Query Based on an Embedded Document Field

You can query a collection based on the value of embedded document fields. To specify an embedded document field, use multiple nested query expressions or standard document dot notation.

For more information, see the Query on Embedded/Nested Documents tutorial in the MongoDB Server Manual.

Nested Query Expressions
{ "<Field Name>": { "<Nested Field Name>": <Value | Expression> } }
Dot Notation
{ "<Field Name>.<Nested Field Name>": <Value | Expression> }

Example

The following query matches documents where the first review in the reviews array was left by someone with the username JoeSchmoe:

{
  "reviews.0.username": "JoeSchmoe"
}

Query Based on an Array of Values

You can query a collection based on all the elements contained in an array field.

If you query an array field for a specific array of values, MongoDB returns documents where the array field exactly matches the specified array of values. If you want MongoDB to return documents where the array field contains all elements in the specified array of values, use the $all operator.

For more information, see the Query an Array tutorial in the MongoDB Server Manual.

{ "<Array Field Name>": [<Value>, ...] }

Example

The following query matches documents where the reviews array contains exactly one element and the element matches the specified document:

{
  "reviews": [{ username: "JoeSchmoe", comment: "This rocks!" }]
}

Example

The following query matches documents where the reviews array contains one or more elements that match all of the the specified documents:

{
  "reviews": {
    "$all": [{ username: "JoeSchmoe", comment: "This rocks!" }]
  }
}

Query Based on an Array Field Element

You can query a collection based on the value of one or more elements in an array field.

If you query an array field with a query expression that has multiple conditions, MongoDB returns documents where any combination of the array’s elements satisfy the expression. If you want MongoDB to return documents where a single array element satisfies all of the expression conditions, use the $elemMatch operator.

For more information, see the Query an Array tutorial in the MongoDB Server Manual.

{ "<Array Field Name>": <Value | Expression> }

Example

The following query matches documents where both conditions in the embedded expression are met by any combination of elements in the reviews array. The specified username and comment values do not need to be in the same document:

{
  "reviews": {
    "username": "JoeSchmoe",
    "comment": "This is a great product!"
  }
}

Example

The following query matches documents where both conditions in the embedded expression are met by a single element in the reviews array. The specified username and comment must be in the same document:

{
  "reviews": {
    "$elemMatch": {
      "username": "JoeSchmoe",
      "comment": "This is a great product!"
    }
  }
}

Query Operators

Compare Values

You can use a comparison operator to compare the value of a document field to another value.

{ "<Field Name>": { "<Comparison Operator>": <Comparison Value> } }

The following comparison operators are available:

Comparison Operator Description
$eq Matches documents where the value of a field equals a specified value.
$ne Matches documents where the value of a field does not equal a specified value.
$gt Matches documents where the value of a field is strictly greater than a specified value.
$gte Matches documents where the value of a field is greater than or equal to a specified value.
$lt Matches documents where the value of a field is strictly less than a specified value.
$lte Matches documents where the value of a field is less than or equal to a specified value.
$in Matches documents where the value of a field is included in a specified array of values.
$nin Matches documents where the value of a field is not included in a specified array of values.

Example

The following query matches documents where quantity is greater than zero and less than or equal to ten.

{
  "quantity": { "$gt": 0, "$lte": 10 }
}

Evaluate a Logical Expression

You can use a logical operator to evaluate multiple expressions for a single field.

{
  "<Field Name>": {
    "<Logical Operator>": [<Expression>, ...]
  }
}

The following logical operators are available:

Logical Operator Description
$and Matches documents where the value of a field matches all of the specified expressions.
$or Matches documents where the value of a field matches any of the specified expressions.
$nor Matches documents where the value of a field matches none of the specified expressions.
$not Inverts the boolean result of the specified logical expression.

Example

The following query matches documents where either quantity is greater than zero or there are no more than five documents in the reviews array.

{
  "$or": [
    { "quantity": { "$gt": 0 } },
    { "reviews": { "$size": { "$lte": 5 } } }
  ]
}

Evaluate a Regular Expression

You can use the $regex query operator to return documents with fields that match a regular expression. To avoid ambiguity with the $regex EJSON type, you must use a BSON.BSONRegExp object.

{
  "<Field Name>": {
    "$regex": BSON.BSONRegExp(<RegEx String>, <RegEx Options>)
  }
}

Example

The following query matches documents where the name value contains the substring ball (case-insensitive).

{
  "name": { "$regex": BSON.BSONRegExp(".+ball", "i") }
}