How to Construct MongoDB Queries from a String using Golang

Introduction to Creating MongoDB queries and filters in Golang

This tutorial will explain how to perform MongoDB queries with Golang. The article will cover how to create bson.M (BSON map) objects from raw JSON strings and from primitve.M BSON objects as well as how to pass those objects to the Golang driver’s method calls to query MongoDB documents. Both MongoDB and the Go driver must be installed on the same sever making the Go API calls.

Prerequisites for Making API Calls to MongoDB queries with the Golang Driver

  • MongoDB must be properly installed and running on the server making the Golang API calls. Type mongod into a terminal window to obtain information on the MongoDB daemon processes.

  • A few documents in a MongoDB collection to use for querying the Golang script with the official MongoDB driver. The following is a screenshot of documents in a MongoDB collection:

Screenshot of documents in a collection on the MongoDB Compass UI

  • To access the attributes and fields of a Golang object, this tutorial utilizes a third-party library called oleiade/reflections to return high-level abstractions of Gonlang’s native, low-level reflect library. Enter the following command in a terminal or command-prompt window to install the package:
go get gopkg.in/oleiade/reflections.v1
  • Golang must be installed and the MongoDB project directory must be in Golang’s $GOPATH . Confirm both are installed and working with the following command:
go get go.mongodb.org/mongo-driver/mongo

References can be located by typing go help gopath or $GOPATH in a terminal window. Enter go help get into a terminal window for additional help with Go’s get command.

How to Import the MongoDB and Go packages in a Golang Script

Execute the folloing command to import the packages to allow MongoDB to create BSON filters, queries and unmarshaled strings in the main() function:

package main

import (
"context" // manage multiple requests
"encoding/json" // Use JSON encoding for bson. M string
"fmt" // Println() function
"log"
"reflect" // get an object type

// import 'mongo-go-driver' package libraries
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive" // for BSON ObjectID
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)

How to Declare a New Struct for the MongoDB Document Fields

Execute the following script to use Golang’s struct datatype to map the MongoDB fields for the collection’s documents:

type MongoFields struct {
Key string `json:"key,omitempty"`
// ObjectId() or objectid. ObjectID is deprecated--use primitive instead
ID primitive. ObjectID `bson:"_id, omitempty"`

// Use these field tags so Golang knows how to map MongoDB fields
// `bson:"string field" json:"string field"`
StringField string `bson:"string field" json:"string field"`
IntField int `bson:"int field" json:"int field"`
BoolField bool `bson:"bool field" json:"bool field"`
}

How to view a collection’s document fields in ‘Mongo Shell’

Enter the following script in Mongo Shell to confirm the exact format of the fields:

mongo shell
use SomeDatabase
db["Some Collection"]
db["Some Collection"].findOne()

Screenshot of mongo Shell in a terminal getting a document in a MongoDB collection

How to Declare the Golang Main() Function and Connect to MongoDB

Execute the below script to declare the main() for the MongoDB API calls and document iteration. These commands will connect to the MongoDB server with mongo.Connect() and then return a client instance that will be used to get a collection’s documents:

func main() {

// Declare host and port options to pass to the Connect() method
clientOptions := options. Client(). ApplyURI("mongodb://localhost:27017")

// Connect to the MongoDB and return Client instance
client, err := mongo. Connect(context. TODO(), clientOptions)
if err != nil {
fmt. Println("mongo. Connect() ERROR:", err)
log. Fatal(err)
}

// Declare Context object for the MongoDB API calls
ctx := context. Background()

// Access a MongoDB collection through a database
col := client. Database("SomeDatabase"). Collection("Some Collection")

NOTE: The "SomeDatabase" and "Some Collection" strings must be replaced with the correct names for the MongoDB database and collection.

How to Declare a BSON Map MongoDB Filter Object

Execute the following command to nest the BSON query into another BSON map object that has one of the collection’s field’s as its key:

filter := bson. M{"int field": bson. M{"$gt":42}}

How to Build a MongoDB Filter Query from a String in Golang

This section will explain how to create a BSON map object for a MongoDB query from a string in Golang and declare a Golang string consisting of a MongoDB JSON filter.

Use backticks to declare a raw string of a valid JSON object in Golang for the MongoDB filter and then instantiate an empty bson.M object for the unmarshaled data to be stored by executing the following command:

// Create a string using ` string escape ticks
query := `{"$eq":"last value"}`

// Declare an empty BSON Map object
var bsonMap bson. M

How to unmarshal a Golang string using the JSON package

Execute the following script to unmarshal the string and return primitive.M :

// Use the JSON package's Unmarshal() method
err = json. Unmarshal([]byte(query), &bsonMap)
if err != nil {
log. Fatal("json. Unmarshal() ERROR:", err)
} else {
fmt. Println("bsonMap:", bsonMap)
fmt. Println("bsonMap TYPE:", reflect. TypeOf(bsonMap))
fmt. Println("BSON:", reflect. TypeOf(bson. M{"int field": bson. M{"$gt":42}}))
}

How to declare a nested ‘bson. M’ MongoDB filter from the ‘primitive. M’ object returned by ‘json. Unmarshal()’

Execute the following command:

// Nest the Unmarshalled BSON map inside another BSON object
filter := bson. M{"string field": bsonMap}

How to use the MongoDB Filter to Return a Cursor Object and Iterate the Documents

Execute the following script to have the Golang driver’s Find() method return a cursor object and iterate the documents by passing a context object to the cursor’s Next() method:

// Pass the filter to Find() to return a MongoDB cursor
cursor, err := col. Find(ctx, filter)
if err != nil {
log. Fatal("col. Find ERROR:", err)
}

// Print cursor object
fmt. Println("\ncursor TYPE:", reflect. TypeOf(cursor))
fmt. Println("cursor:", cursor)

// iterate through all documents
for cursor. Next(ctx) {
var p MongoFields

// Decode the document
if err := cursor. Decode(&p); err != nil {
log. Fatal("cursor. Decode ERROR:", err)
}
// Print the results of the iterated cursor object
fmt. Printf("\nMongoFields: %+v\n", p)
}
}

Conclusion

This tutorial explained how to create MongoDB queries with Golang using strings and BSON map objects. The article covered how to create BSON map objects from raw JSON strings and primitve.M BSON objects and explained how to pass those to the Golang driver’s method calls to query MongoDB documents. This tutorial also covered how to import the MongoDB and Go packages in a Golang script, how to unmarshal a Golang string using the JSON package, how to build a MongoDB filter query from a string in Golang and how to use the MongoDB filter to return a cursor object and iterate the documents. Remember that the "SomeDatabase" and "Some Collection" strings must be replaced with the correct names for the MongoDB database and collection.

Just the Code

package main

import (
"context" // manage multiple requests
"encoding/json" // Use JSON encoding for bson. M string
"fmt" // Println() function
"log"
"reflect" // get an object type

// import 'mongo-go-driver' package libraries
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive" // for BSON ObjectID
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)

type MongoFields struct {
Key string `json:"key,omitempty"`
// ObjectId() or objectid. ObjectID is deprecated--use primitive instead
ID primitive. ObjectID `bson:"_id, omitempty"`

// Use these field tags so Golang knows how to map MongoDB fields
// `bson:"string field" json:"string field"`
StringField string `bson:"string field" json:"string field"`
IntField int `bson:"int field" json:"int field"`
BoolField bool `bson:"bool field" json:"bool field"`
}

func main() {

// Declare host and port options to pass to the Connect() method
clientOptions := options. Client(). ApplyURI("mongodb://localhost:27017")

// Connect to the MongoDB and return Client instance
client, err := mongo. Connect(context. TODO(), clientOptions)
if err != nil {
fmt. Println("mongo. Connect() ERROR:", err)
log. Fatal(err)
}

// Declare Context object for the MongoDB API calls
ctx := context. Background()

// Access a MongoDB collection through a database
col := client. Database("SomeDatabase"). Collection("Some Collection")

// Typical BSON Map filter
//filter := bson. M{"int field": bson. M{"$gt":42}}

// Create a string using ` string escape ticks
query := `{"$eq":"last value"}`

// Declare an empty BSON Map object
var bsonMap bson. M

// Use the JSON package's Unmarshal() method
err = json. Unmarshal([]byte(query), &bsonMap)
if err != nil {
log. Fatal("json. Unmarshal() ERROR:", err)
} else {
fmt. Println("bsonMap:", bsonMap)
fmt. Println("bsonMap TYPE:", reflect. TypeOf(bsonMap))
fmt. Println("BSON:", reflect. TypeOf(bson. M{"int field": bson. M{"$gt": 42}}))
}

// Nest the Unmarshalled BSON map inside another BSON object
filter := bson. M{"string field": bsonMap}

// Pass the filter to Find() to return a MongoDB cursor
cursor, err := col. Find(ctx, filter)
if err != nil {
log. Fatal("col. Find ERROR:", err)
}

// Print cursor object
fmt. Println("\ncursor TYPE:", reflect. TypeOf(cursor))
fmt. Println("cursor:", cursor)

// iterate through all documents
for cursor. Next(ctx) {
var p MongoFields

// Decode the document
if err := cursor. Decode(&p); err != nil {
log. Fatal("cursor. Decode ERROR:", err)
}
// Print the results of the iterated cursor object
fmt. Printf("\nMongoFields: %+v\n", p)
}
}

Pilot the ObjectRocket platform free for 30 Days

It's easy to get started. Imagine the time you'll save by not worrying about database management. Let's do this!

PILOT FREE FOR 30 DAYS

Keep in the know!

Subscribe to our emails and we’ll let you know what’s going on at ObjectRocket. We hate spam and make it easy to unsubscribe.