Indexes Using Official Mongo-Go Driver

Mayur Wadekar
4 min readApr 26, 2020

--

Mongo-Gopher

MongoDB is a NoSQL database that has no structure defined for its documents. While comparing to the structured database MongoDB is the unstructured database.

“MongoDB is sometimes referred to as a “schemaless” database, meaning that it does not enforce a particular structure on documents in a collection. It is perfectly legal (though of questionable utility) to store every object in your application in the same collection, regardless of its structure.” — Rick Copeland

Many large scale applications where data is stored and live reports were served were indexes are very important. While if those collections are not already present in the database and created through the program(code), they are not having indexes and getting slower. MongoDB is having a spectacular property within it as it creates collection if not present. And that time realization is like if no index is present on collection then it scans the whole collection to search particular data.

So real question arises where if collection creates programmatically then how to create indexes on them. So let’s get started.

1. Database Connection

Following simple function creates database connection in official Mongo-Go driver. I have created a package db to get a connection from the database.

package dbimport (
"context"
"fmt"
"sync"
"time"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"go.mongodb.org/mongo-driver/mongo/readpref"
)
// single instance variables
var instance *mongo.Client
var mutex sync.Mutex
var once sync.Once
var (
username = ""
password = ""
dbname = ""
poolLimit = 100
)
// GetConnection - return mongodb connection
func GetConnection() (*mongo.Client, error) {
once.Do(func() {
defer mutex.Unlock()
mutex.Lock()
clientOption := options.Client()
clientOption.SetHosts([]string{"localhost:27017"}).
SetConnectTimeout(time.Second * 3). // sets connection timeout
SetMaxPoolSize(uint64(poolLimit)). // sets connectionpool limit
SetReadPreference(readpref.Primary()) // sets read from primary database
// if username not blank then only perform authentication
if username != "" {
cred := options.Credential{}
cred.Username = username
cred.Password = password
cred.AuthSource = dbname
clientOption.SetAuth(cred)
}

client, err := mongo.NewClient(clientOption)
if err != nil {
fmt.Errorf(err.Error())
return
}
err = client.Connect(context.Background())
if err != nil {
fmt.Errorf(err.Error())
return
}
err = client.Ping(context.Background(), readpref.Primary())
if err != nil {
fmt.Errorf(err.Error())
return
}
instance = client})return instance, nil
}

2. Database Services

In that part, I have created a simple function that how to create an index on collection. In that function argument, you have to pass your key on which you wanted to create an index. For creating indexes we have using package go.mongodb.org/mongo-driver/x/bsonx.

package dbServicesimport (
"context"
"fmt"
"time"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"go.mongodb.org/mongo-driver/x/bsonx"
)
// EnsureIndex will create index on collection provided
func EnsureIndex(cd *mongo.Collection, indexQuery []string) error {
opts := options.CreateIndexes().SetMaxTime(3 * time.Second)

index := []mongo.IndexModel{}

for _, val := range indexQuery {
temp := mongo.IndexModel{}
temp.Keys = bsonx.Doc{{Key: val, Value: bsonx.Int32(1)}}
index = append(index, temp)
}
_, err := cd.Indexes().CreateMany(context.Background(), index, opts)
if err != nil {
fmt.Errorf("Error while executing index Query", err.Error())
return err
}
return nil}

The SetMaxTime() method specifies the maximum amount of time to allow the query to run. So parameter may vary as per your collection data size you inserting. Suppose you inserted a single document then the timeout will be 1 second sufficient but you have inserted 5000000 records then the timeout will be 25–30 seconds for executing a query. (I have tested 52265 records executed in 3.25 seconds and document size is about 3KB size. But in your case it may vary as per your machine and other parameters).

3. Main Function

Now all the functions above defined are used in main.

package mainimport (
"Go_Exercise/mongo-go-driver/db"
dbservices "Go_Exercise/mongo-go-driver/dbServices"
"context"
"fmt"
"go.mongodb.org/mongo-driver/bson"
)

func main() {
session, err := db.GetConnection()
if err != nil {
fmt.Errorf("Error while getting database connection ", err.Error())
return
}
// database and collection
cd := session.Database("testDB").Collection("newColl")
_, err = cd.InsertOne(context.Background(), bson.M{"rollNo": 1, "name": "Mayur Wadekar"})
if err != nil {
fmt.Errorf("Error while inserting document in connection ", err.Error())
return
}
err = dbservices.EnsureIndex(cd, []string{"rollNo"}) // rollNo index will be added for newColl collection
if err != nil {
fmt.Errorf("Error while creating index on connection ", err.Error())
return
}
fmt.Println("Everythin works fine... :)")}

OUTPUT

  1. Before main program execution:
No Collection and Indexes

2. After main program execution:

Collection created and index added

Platform:

  1. Go: 1.10
  2. Mongo-Go Driver: 1.2.0
  3. MongoDB: 3.6.0

You can see the whole code here on Github.

--

--