Golang MongoDb raw pagination

I’m writing a complex query (for a beginner user) for mongodb using the golang official driver, i’d like share my code to help other user.

I’ll use an aggragate to do the complex query, we need to step the first one to count the records of the query, the second step to get the elements at the request page.

var basePipeline = mongo.Pipeline{
 {{“$lookup”, bson.D{
 {“from”, “makers”},
 {“localField”, “maker”},
 {“foreignField”, “username”},
 {“as”, “makerinfo”},
 }}}}



The first piece fo the pipeline is the lookup, a similar left-join, we want join from the collection of products the makers. With the subpipeline we specify the conditions of the query:

var countPipeline mongo.Pipeline
var productsPipeline mongo.Pipeline
subpipeline := bson.D{
 {“$match”, bson.D{{“$and”,
 bson.A{
 bson.D{{“name”, bson.M{“$regex”: “.*” + initial + “.*”, “$options”: “-i”}}},
 bson.D{{“makers”, maker}},
 }}



I use two different pipeline, the countPipeline to count of the products, the second to gets the products. To have the count we must add other pipeline:

var countPipeline mongo.Pipeline
var productsPipeline mongo.Pipeline
subpipeline := bson.D{
        {"$match", bson.D{{"$and",
            bson.A{
                bson.D{{"name", bson.M{"$regex": ".*" + initial + ".*", "$options": "-i"}}},
                bson.D{{"makers", maker}},
        }}
countPipeline = append(basePipeline, subpipeline)
countCondition := bson.D{{"$count", "numberOfProduct"}}
countPipeline = append(countPipeline, countCondition)
productsPipeline = append(basePipeline, subpipeline)
 
cur, err = GetDB().Collection("products").Aggregate(GetCtx(), countPipeline)
// number of elements
var total int
if err != nil {
  fmt.Printf("[Debug] decode error %s", err)
  panic(err)
 } else {
  for cur.Next(GetCtx()) {
   dum := bson.M{"np": 0}
   if err = cur.Decode(&dum); err != nil {
    fmt.Printf("[Debug] decode error %s", err)
   }
   total = int(dum["numberOfProduct"].(int32))
  }
 }


Verify the page is in the range of the pages

// number of page
pages := total / 10
if (total % 10) > 0 {
  pages++
}
jumpPage, conError := strconv.Atoi(page)
if pages == 0 || conError != nil || jumpPage > pages {
  finalResult := bson.M{"products": result, "productsCount": 0, "pages": 0}
  return finalResult
}



Finally to gets the elements of the page:

result := []bson.M{}
var nProducts = 0
// get elements
jumpPagePipeline := bson.D{{"$skip", jumpPage}}
limitPipeline := bson.D{{"$limit", 10}}
productsPipeline = append(productsPipeline, jumpPagePipeline)
productsPipeline = append(productsPipeline, limitPipeline)
cur, err = GetDB().Collection("products").Aggregate(GetCtx(), productsPipeline)
// number of elements
if err != nil {
  fmt.Printf("[Debug] decode error %s", err)
  panic(err)
 } else {
  for cur.Next(GetCtx()) {
   dum := bson.M{}
   //var resultDecode bson.M
   if err = cur.Decode(&dum); err != nil {
    fmt.Printf("[Debug] decode error %s", err)
   }
   result = append(result, dum)
   nProducts++
  }
 }
finalResult := bson.M{"products": result, "productsCount": nProducts}



I used jumpedPipeline to jump to the page and limit to get only 10 elemets for page.

This example is not the better way to do the pagination, but it can be helpful to understand how build complex query.


For some better code you can see:

https://github.com/gobeam/mongo-go-pagination (it’s not my code)

share this post with friends

Picture of Nicola De filippo

Nicola De filippo

I'm a software engineer who adds to the passion for technologies the wisdom and the experience without losing the wonder for the world. I love to create new projects and to help people and teams to improve

Leave a comment

Your email address will not be published. Required fields are marked *

Who I am

I'm a software engineer who adds to the passion for technologies the wisdom and the experience without losing the wonder for the world. I love to create new projects and to help people and teams to improve.

Follow Me Here

Get The Latest Updates

Periodically receive my super contents on coding and programming

join the family;)

Recent Posts