How to Get MongoDB Documents Using Golang
Introduction
If you’re interested in using the Golang language to communicate with your instance of MongoDB, it’s easy to accomplish this with the help of the Golang driver for MongoDB. Once the driver is installed, it’s easy to connect to MongoDB from your Golang script with just a few lines of code. In this article, we’ll show you how to connect to MongoDB and find documents with Golang.
Prerequisites for using the Golang driver for MongoDB
Let’s go over some important prerequisites that need to be in place before proceeding with this tutorial:
First, the MongoDB server needs to be running. You can use the mongo
command in a terminal or command prompt window to see if it’s running by trying to enter the Mongo Shell. If this returns an error, you’ll know the server isn’t running.
The Golang driver for MongoDB needs to be installed, and the environmental variables for Golang need to be set in the bash profile shell script. You can use the go get
command to check if a package is installed:
1 | go get go.mongodb.org/mongo-driver/mongo |
- Be sure you have at least a few MongoDB documents already stored in a collection in order to get the most out of the examples in this tutorial.
Create a new Golang script and import the packages for MongoDB
Now that we’ve discussed the system requirements, we can focus on our code. Let’s begin by creating a new file using the .go
file extension; you can do this using the touch
command in a terminal window. Be sure to create this file in the same directory path as your Golang projects. If you’re not sure of the directory path, type $GOPATH
in a terminal or command prompt window, and it should return this information.
Import the MongoDB packages and other Golang package libraries
Our next step will be to place package main
at the top of the file. We’ll also use Go’s import()
declaration to include all of the necessary packages for the MongoDB API calls. The code below shows the various packages we’re importing in this example, including the mongodb-driver package for Golang:
1 2 3 4 5 6 7 8 9 10 11 12 | package main import ( "context" // manage multiple requests "fmt" // Println() function "reflect" // get an object type "time" // import 'mongo-driver' package libraries "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson/primitive" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" ) |
Create a struct object of the MongoDB fields
In order to get the MongoDB data returned by the API call, it’s important to first declare a struct
object. This object will contain all of the collection fields you’d like the API call to return.
In the following example, we declare a struct
to marshal the MongoDB data outside of the main()
function:
1 2 3 4 5 | type Fields struct { Name string Email string Dept int } |
Note that each field in the struct needs to be accompanied by a data type.
Create a struct
object in the Go script for the MongoDB fields returned by API call
Connect to MongoDB using the mongo.Connect() method
Next, we’ll declare the main()
function, which is where all of the code in the script will be executed:
1 | func main() { |
Connect to MongoDB using the package’s Connect()
method
After we declare our main()
function, we can use the options.Client()
method and have it return a options.ClientOptions
object. We can then pass that object to the mongo.Connect
method to declare a new client instance and check for errors. The code to accomplish this is shown below:
1 2 3 4 5 6 7 8 9 | // Declare host and port options to pass to the Connect() method clientOptions := options.Client().ApplyURI("mongodb://localhost:27017") fmt.Println("clientOptions type:", reflect.TypeOf( clientOptions ), "\n") // Connect to the MongoDB and return Client instance client, err := mongo.Connect(context.TODO(), clientOptions) if err != nil { fmt.Println("mongo.Connect() ERROR:", err) os.Exit(1) } |
Use Golang’s Context package to manage the MongoDB API requests
We’ll also need to declare a new context instance– this can assist with managing timeouts for the MongoDB API requests:
1 2 | // Declare Context type object for managing multiple API requests ctx, _ := context.WithTimeout(context.Background(), 15*time.Second) |
This context instance, which we named ctx
, can be passed to multiple API calls, and it works well when you’re dealing with concurrent channels and multiple goroutines
.
Declare a collection instance using the client instance of the mongo-driver package
Now let’s use the :=
Golang operator to declare a new Collection()
instance and assign it to a variable using the client
instance we created earlier:
1 2 3 | // Access a MongoDB collection through a database col := client.Database("employees").Collection("New Hires") fmt.Println("Collection type:", reflect.TypeOf(col), "\n") |
Use the FindOne() method to return a MongoDB document in Golang
Once we have a collection object, we can go ahead and make API calls to the MongoDB server using the mongo-driver
package.
Use var
to declare an instance of the Fields struct
object
Here, we use the var
statement to declare an instance of the “Fields” struct
. The API call can then return document results to this instance:
1 2 | // declare an instance of the MongoDB fields struct var result Fields |
Call the collection instance’s FindOne()
method
We can communicate with MongoDB using FindOne in Golang. The FindOne()
method will only return an error object. If you’d like to overwrite the data from the err
object used earlier, you’ll need to assign it a new value using the =
operator; otherwise, you can use a new variable name (like err2
) and use the :=
declarative operator instead.
Simply pass an empty bson.D{}
object to the FindOne()
method call since no query or filter is necessary:
1 2 | // get a MongoDB document using the FindOne() method err = col.FindOne(context.TODO(), bson.D{}).Decode(&result) |
Note that we use the Decode()
attribute method to actually get a document– we accomplish this by passing the result
struct instance to it.
Parse the result
object returned by the mongo-driver
API call
When the err
object is returned, evaluate it to make sure it has a value of nil
, which means that no errors were raised. If there were no errors, you can then get the document’s data by accessing the various attributes of the struct object. An example of this is shown below:
1 2 3 4 5 6 7 8 | if err != nil { fmt.Println("Error calling FindOne():", err) os.Exit(1) } else { fmt.Println("FindOne() result:", result) fmt.Println("FindOne() Name:", result.Name) fmt.Println("FindOne() Dept:", result.Dept) } |
Use the MongoDB Golang driver to return all of a collection’s documents
Now we’ll pass another empty bson.D{}
object to the driver’s Find()
method. This step has the MongoDB driver return all of the collection’s documents:
1 2 | // call the collection's Find() method and return Cursor obj cursor, err := col.Find(context.TODO(), bson.D{}) |
Iterate over the MongoDB documents returned by the Golang driver’s Find()
method
As we did in the previous example, the first thing we’ll do here is to check if the API call returned any errors by evaluating the err
object for the Find() method call:
1 2 3 4 | // Find() method raised an error if err != nil { fmt.Println("Finding all documents ERROR:", err) defer cursor.Close(ctx) |
If there are no errors, then we’ll use the cursor
object’s Next()
method to iterate over the MongoDB documents. As we go through these documents, we’ll check for errors and create a BSON result object in the process:
1 2 3 4 5 6 7 | // If the API call was a success } else { // iterate over docs using Next() for cursor.Next(ctx) { // Declare a result BSON object var result bson.M err := cursor.Decode(&result) |
If we find an error, we’ll print it out and exit the application; otherwise, we’ll print the results of the cursor.Decode()
method call:
1 2 3 4 5 6 7 8 9 10 11 12 | // If there is a cursor.Decode error if err != nil { fmt.Println("cursor.Next() error:", err) os.Exit(1) // If there are no cursor.Decode errors } else { fmt.Println("\nresult type:", reflect.TypeOf(result)) fmt.Println("result:", result) } } } } |
Conclusion
As you can see, it’s not difficult to connect to MongoDB and retrieve documents from a collection using the Golang programming language. In this tutorial, we saw examples of getting a single document as well as all documents, and we learned how to examine the returned object for errors before parsing the results. With these step-by-step instructions, you’ll be able to write your own script to get a MongoDB document with Golang.
Just the Code
Shown below is the example code in its entirety:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | package main import ( "context" // manage multiple requests "fmt" // Println() function "os" "reflect" // get an object type "time" // import 'mongo-driver' package libraries "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" ) type Fields struct { Name string Email string Dept int } func main() { // Declare host and port options to pass to the Connect() method clientOptions := options.Client().ApplyURI("mongodb://localhost:27017") fmt.Println("clientOptions type:", reflect.TypeOf(clientOptions), "\n") // Connect to the MongoDB and return Client instance client, err := mongo.Connect(context.TODO(), clientOptions) if err != nil { fmt.Println("mongo.Connect() ERROR:", err) os.Exit(1) } // Declare Context type object for managing multiple API requests ctx, _ := context.WithTimeout(context.Background(), 15*time.Second) // Access a MongoDB collection through a database col := client.Database("employees").Collection("New Hires") fmt.Println("Collection type:", reflect.TypeOf(col), "\n") // Declare an empty array to store documents returned var result Fields // Get a MongoDB document using the FindOne() method err = col.FindOne(context.TODO(), bson.D{}).Decode(&result) if err != nil { fmt.Println("FindOne() ERROR:", err) os.Exit(1) } else { fmt.Println("FindOne() result:", result) fmt.Println("FindOne() Name:", result.Name) fmt.Println("FindOne() Dept:", result.Dept) } // Call the collection's Find() method to return Cursor obj // with all of the col's documents cursor, err := col.Find(context.TODO(), bson.D{}) // Find() method raised an error if err != nil { fmt.Println("Finding all documents ERROR:", err) defer cursor.Close(ctx) // If the API call was a success } else { // iterate over docs using Next() for cursor.Next(ctx) { // declare a result BSON object var result bson.M err := cursor.Decode(&result) // If there is a cursor.Decode error if err != nil { fmt.Println("cursor.Next() error:", err) os.Exit(1) // If there are no cursor.Decode errors } else { fmt.Println("\nresult type:", reflect.TypeOf(result)) fmt.Println("result:", result) } } } } |
Pilot the ObjectRocket Platform Free!
Try Fully-Managed CockroachDB, Elasticsearch, MongoDB, PostgreSQL (Beta) or Redis.
Get Started