Docs Menu
Docs Home
/ / /
Go Driver
/ /

Find Documents

In this guide, you can learn how to retrieve data from your MongoDB collections using read operations.

Read operations allow you to do the following:

  • Retrieve documents from your collections by using find operations

  • Perform transformations on documents in your collections by using aggregation operations

The examples in this guide use the following Tea struct as a model for documents in the tea collection:

type Tea struct {
Item string `bson:"item,omitempty"`
Rating int32 `bson:"rating,omitempty"`
DateOrdered time.Time `bson:"date_ordered,omitempty"`
}

To run the examples in this guide, load these documents into the tea collection in the db database by using the following snippet:

coll := client.Database("db").Collection("tea")
docs := []interface{}{
Tea{Item: "Masala", Rating: 10, DateOrdered: time.Date(2009, 11, 17, 0, 0, 0, 0, time.Local)},
Tea{Item: "Sencha", Rating: 7, DateOrdered: time.Date(2009, 11, 18, 0, 0, 0, 0, time.Local)},
Tea{Item: "Masala", Rating: 9, DateOrdered: time.Date(2009, 11, 12, 0, 0, 0, 0, time.Local)},
Tea{Item: "Masala", Rating: 8, DateOrdered: time.Date(2009, 12, 1, 0, 0, 0, 0, time.Local)},
Tea{Item: "Sencha", Rating: 10, DateOrdered: time.Date(2009, 12, 17, 0, 0, 0, 0, time.Local)},
Tea{Item: "Hibiscus", Rating: 4, DateOrdered: time.Date(2009, 12, 18, 0, 0, 0, 0, time.Local)},
}
result, err := coll.InsertMany(context.TODO(), docs)

Tip

Nonexistent Databases and Collections

If the necessary database and collection don't exist when you perform a write operation, the server implicitly creates them.

Each document describes the tea variety a customer ordered, their rating, and the date of the order. These descriptions correspond to the item, rating, and date_ordered fields.

Use find operations to retrieve data from MongoDB. Find operations consist of the Find() and FindOne() methods.

The Find() method expects you to pass a Context type and a query filter. The method returns all documents that match the filter as a Cursor type.

The following example passes a context, filter, and FindOptions to the Find() method, which performs the following actions:

  • Matches documents where the rating value is between 5 and 9 (exclusive)

  • Sorts the matched documents in ascending order by date_ordered

filter := bson.D{
{"$and",
bson.A{
bson.D{{"rating", bson.D{{"$gt", 5}}}},
bson.D{{"rating", bson.D{{"$lt", 9}}}},
}},
}
sort := bson.D{{"date_ordered", 1}}
opts := options.Find().SetSort(sort)
// Retrieves documents that match the filter and prints them as structs
cursor, err := coll.Find(context.TODO(), filter, opts)
if err != nil {
panic(err)
}
var results []Tea
if err = cursor.All(context.TODO(), &results); err != nil {
panic(err)
}
for _, result := range results {
res, _ := bson.MarshalExtJSON(result, false, false)
fmt.Println(string(res))
}
{"item":"Sencha","rating":7,"date_ordered":"2009-11-18T05:00:00Z"}
{"item":"Masala","rating":8,"date_ordered":"2009-12-01T05:00:00Z"}

To learn how to access data by using a cursor, see the Access Data From a Cursor guide.

Note

Example Setup

This example connects to an instance of MongoDB by using a connection URI. To learn more about connecting to your MongoDB instance, see the Create a MongoClient guide. This example also uses the restaurants collection in the sample_restaurants database included in the Atlas sample datasets. You can load them into your database on the free tier of MongoDB Atlas by following the Get Started with Atlas Guide.

The following example finds all documents in the restaurants collection in which the value of cuisine is "Italian". The example returns a cursor that references the matched documents and unpacks the documents into a slice:

// Retrieves documents that match a query filter by using the Go driver
package main
import (
"context"
"encoding/json"
"fmt"
"log"
"os"
"github.com/joho/godotenv"
"go.mongodb.org/mongo-driver/v2/bson"
"go.mongodb.org/mongo-driver/v2/mongo"
"go.mongodb.org/mongo-driver/v2/mongo/options"
)
// Creates a Restaurant struct as a model for documents in the restaurants collection
type Restaurant struct {
ID bson.ObjectID `bson:"_id"`
Name string
RestaurantId string `bson:"restaurant_id"`
Cuisine string
Address interface{}
Borough string
Grades interface{}
}
func main() {
if err := godotenv.Load(); err != nil {
log.Println("No .env file found")
}
var uri string
if uri = os.Getenv("MONGODB_URI"); uri == "" {
log.Fatal("You must set your 'MONGODB_URI' environment variable. See\n\t https://www.mongodb.com/docs/drivers/go/current/connect/mongoclient/#environment-variable")
}
client, err := mongo.Connect(options.Client().ApplyURI(uri))
if err != nil {
panic(err)
}
defer func() {
if err = client.Disconnect(context.TODO()); err != nil {
panic(err)
}
}()
coll := client.Database("sample_restaurants").Collection("restaurants")
// Creates a query filter to match documents in which the "cuisine"
// is "Italian"
filter := bson.D{{"cuisine", "Italian"}}
// Retrieves documents that match the query filter
cursor, err := coll.Find(context.TODO(), filter)
if err != nil {
panic(err)
}
// Unpacks the cursor into a slice
var results []Restaurant
if err = cursor.All(context.TODO(), &results); err != nil {
panic(err)
}
// Prints the results of the find operation as structs
for _, result := range results {
output, err := json.MarshalIndent(result, "", " ")
if err != nil {
panic(err)
}
fmt.Printf("%s\n", output)
}
}
// results truncated
...
{ ... , "Name" : "Epistrophy Cafe", "RestaurantId": "41117553", "Cuisine" : "Italian", ... },
{ ... , "Name" : "Remi", "RestaurantId": "41118090", "Cuisine" : "Italian", ... },
{ ... , "Name" : "Sant Ambroeus", "RestaurantId": "41120682", "Cuisine" : "Italian", ... },
...

The FindOne() method expects you to pass a Context type and a query filter. The method returns the first document that matches the filter as a SingleResult type.

The following example passes a context, filter, and FindOneOptions to the FindOne() method, which performs the following actions:

  • Matches documents where the date_ordered value is on or before November 30, 2009

  • Skips the first two matched documents

filter := bson.D{{"date_ordered", bson.D{{"$lte", time.Date(2009, 11, 30, 0, 0, 0, 0, time.Local)}}}}
opts := options.FindOne().SetSkip(2)
// Retrieves a document that matches the filter and prints it as
// a struct
var result Tea
err = coll.FindOne(context.TODO(), filter, opts).Decode(&result)
if err != nil {
if err == mongo.ErrNoDocuments {
fmt.Println("No documents found")
} else {
panic(err)
}
}
res, _ := bson.MarshalExtJSON(result, false, false)
fmt.Println(string(res))
{"item":"Masala","rating":9,"date_ordered":"2009-11-12T05:00:00Z"}

For an example that uses FindOne() and queries by using a specific ObjectId value, see the Find One by ObjectId Example section of this page.

To learn how to access data from a SingleResult type, see Unmarshalling in the BSON guide.

This example defines an id variable with a value of type ObjectId and uses id to specify a query filter. The filter matches a document with an _id field value that corresponds to the id variable. This example queries for the following document based on its _id value:

{
_id: ObjectId('65170b42b99efdd0b07d42de'),
item: "Hibiscus",
rating : 4,
date_ordered : 2009-12-18T05:00:00.000+00:00
}

The following code passes the filter and a FindOneOptions instance as parameters to the FindOne() method to perform the following actions:

  • Match the document with the specified ObjectId value

  • Project only the Item and Rating fields of the matched document

id, err := bson.ObjectIDFromHex("65170b42b99efdd0b07d42de")
if err != nil {
panic(err)
}
// Creates a filter to match a document that has the specified
// "_id" value
filter := bson.D{{"_id", id}}
opts := options.FindOne().SetProjection(bson.D{{"item", 1}, {"rating", 1}})
// Retrieves a document that matches the filter and prints it as
// a struct
var result Tea
err = coll.FindOne(context.TODO(), filter, opts).Decode(&result)
if err != nil {
if err == mongo.ErrNoDocuments {
fmt.Println("No documents found")
} else {
panic(err)
}
}
res, _ := bson.MarshalExtJSON(result, false, false)
fmt.Println(string(res))
{"item":"Hibiscus","rating":4}

Note

The Go driver automatically generates a unique ObjectId value for each document's _id field, so your ObjectId value might differ from the preceding code example. For more information about the _id field, see the _id Field section of the Insert a Document page.

Note

Example Setup

This example connects to an instance of MongoDB by using a connection URI. To learn more about connecting to your MongoDB instance, see the Create a MongoClient guide. This example also uses the restaurants collection in the sample_restaurants database included in the Atlas sample datasets. You can load them into your database on the free tier of MongoDB Atlas by following the Get Started with Atlas Guide.

The following example finds and returns the first document in the restaurants collection in which the value of name is "Bagels N Buns":

// Retrieves a document that matches a query filter by using the Go driver
package main
import (
"context"
"encoding/json"
"fmt"
"log"
"os"
"github.com/joho/godotenv"
"go.mongodb.org/mongo-driver/v2/bson"
"go.mongodb.org/mongo-driver/v2/mongo"
"go.mongodb.org/mongo-driver/v2/mongo/options"
)
// Creates a Restaurant struct as a model for documents in the restaurants collection
type Restaurant struct {
ID bson.ObjectID `bson:"_id"`
Name string
RestaurantId string `bson:"restaurant_id"`
Cuisine string
Address interface{}
Borough string
Grades []interface{}
}
func main() {
if err := godotenv.Load(); err != nil {
log.Println("No .env file found")
}
var uri string
if uri = os.Getenv("MONGODB_URI"); uri == "" {
log.Fatal("You must set your 'MONGODB_URI' environment variable. See\n\t https://www.mongodb.com/docs/drivers/go/current/connect/mongoclient/#environment-variable")
}
client, err := mongo.Connect(options.Client().ApplyURI(uri))
if err != nil {
panic(err)
}
defer func() {
if err = client.Disconnect(context.TODO()); err != nil {
panic(err)
}
}()
coll := client.Database("sample_restaurants").Collection("restaurants")
// Creates a query filter to match documents in which the "name" is
// "Bagels N Buns"
filter := bson.D{{"name", "Bagels N Buns"}}
// Retrieves the first matching document
var result Restaurant
err = coll.FindOne(context.TODO(), filter).Decode(&result)
// Prints a message if no documents are matched or if any
// other errors occur during the operation
if err != nil {
if err == mongo.ErrNoDocuments {
return
}
panic(err)
}
output, err := json.MarshalIndent(result, "", " ")
if err != nil {
panic(err)
}
fmt.Printf("%s\n", output)
}
// results truncated
{
"ID": "5eb3d668b31de5d588f42950",
"Name": "Bagels N Buns",
"RestaurantId": "40363427"
"Address": [...],
"Borough": "Staten Island",
"Cuisine": "Delicatessen",
"Grades": [...]
}

You can modify the behavior of Find() and FindOne() by passing a FindOptions or FindOneOptions instance. If you don't specify any options, the driver uses the default values for each option.

You can configure the commonly used options in both types with the following methods:

Method
Description

SetCollation()

The type of language collation to use when sorting results.
Default: nil

SetLimit()

The maximum number of documents to return.
Default: 0
This option is not available for FindOneOptions. The FindOne() method internally uses SetLimit(-1).

SetProjection()

The fields to include in the returned documents.
Default: nil

SetSkip()

The number of documents to skip.
Default: 0

SetSort()

The field and type of sort to order the matched documents. You can specify an ascending or descending sort.
Default: none

Use aggregation operations to retrieve and transform data from MongoDB. Perform aggregation operations using the Aggregate() method.

The Aggregate() method expects you to pass a Context type and an aggregation pipeline. An aggregation pipeline defines how to transform data through stages. Some of the stages are matching documents, renaming fields, and grouping values.

The method returns the resulting documents in a Cursor type. If you omit the $match stage, the pipeline proceeds using all documents in the collection.

To learn how to access data in a cursor, see Access Data From a Cursor.

The Aggregate() method optionally takes an AggregateOptions type, which represents options you can use to modify its behavior. If you don't specify any options, the driver uses the default values for each option.

The AggregateOptions type allows you to configure options with the following methods:

Method
Description

SetAllowDiskUse()

Whether to write to temporary files.
Default: false

SetBatchSize()

The number of documents to return in each batch.
Default: none

SetBypassDocumentValidation()

Whether to allow the write to opt-out of document level validation.
Default: false

SetCollation()

The type of language collation to use when sorting results.
Default: nil

SetMaxAwaitTime()

The maximum amount of time for the server to wait on new documents to satisfy a tailable cursor query.
Default: nil

SetComment()

An arbitrary string or document that allows you to trace the operation through the database profiler, currentOp, and logs.
Default: ""

SetHint()

The index to use to scan for documents to retrieve.
Default: nil

SetLet()

Specifies parameters for the aggregate expression, which improves command readability by separating the variables from the query text.
Default: none

The following example passes a context and an aggregation pipeline that performs the following actions:

  • Groups reviews by item ordered

  • Calculates the average rating for each item

groupStage := bson.D{
{"$group", bson.D{
{"_id", "$item"},
{"average", bson.D{
{"$avg", "$rating"},
}},
}}}
cursor, err := coll.Aggregate(context.TODO(), mongo.Pipeline{groupStage})
if err != nil {
panic(err)
}
// Prints the average "rating" for each item
var results []bson.M
if err = cursor.All(context.TODO(), &results); err != nil {
panic(err)
}
for _, result := range results {
fmt.Printf("%v had an average rating of %v \n", result["_id"], result["average"])
}
Sencha had an average rating of 8.5
Hibiscus had an average rating of 4
Masala had an average rating of 9

To learn more about how to construct an aggregation pipeline, see the MongoDB server manual page on Aggregation.

To learn more about the operations mentioned, see the following guides:

To learn more about any of the methods or types discussed in this guide, see the following API Documentation:

Back

Specify a Query

On this page