Skip to content

Commit

Permalink
web api added to simulate example
Browse files Browse the repository at this point in the history
  • Loading branch information
gobeam committed Jun 21, 2021
1 parent 86e6376 commit d16b35a
Showing 1 changed file with 185 additions and 55 deletions.
240 changes: 185 additions & 55 deletions example/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,89 +2,219 @@ package main

import (
"context"
"encoding/json"
"fmt"
paginate "github.com/gobeam/mongo-go-pagination"
"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"
"time"
"log"
"net/http"
"strconv"
)

// Product struct
type Product struct {
Id primitive.ObjectID `json:"_id" bson:"_id"`
Name string `json:"name" bson:"name"`
Quantity float64 `json:"qty" bson:"qty"`
Price float64 `json:"price" bson:"price"`
Id primitive.ObjectID `json:"_id,omitempty" bson:"_id"`
Name string `json:"name,omitempty" bson:"name"`
Quantity float64 `json:"qty,omitempty" bson:"qty"`
Price float64 `json:"price,omitempty" bson:"price"`
}

func main() {
// Establishing mongo db connection
ctx, _ := context.WithTimeout(context.Background(), 10*time.Second)
client, err := mongo.Connect(ctx, options.Client().ApplyURI("mongodb://localhost:27017"))
func insertExamples(db *mongo.Database) (insertedIds []interface{}, err error) {
var data []interface{}
for i := 0; i < 30; i++ {
data = append(data, bson.M{
"name": fmt.Sprintf("product-%d", i),
"quantity": float64(i),
"Price": float64(i*10+5),
})
}
result, err := db.Collection("products").InsertMany(
context.Background(), data)
if err != nil {
panic(err)
return nil, err
}
return result.InsertedIDs, nil
}

// Example for Normal Find query
filter := bson.M{}
var limit int64 = 10
var page int64 = 1
collection := client.Database("myaggregate").Collection("stocks")
projection := bson.D{
{"name", 1},
{"qty", 1},
}
// Querying paginated data
// If you want to do some complex sort like sort by score(weight) for full text search fields you can do it easily
// sortValue := bson.M{
// "$meta" : "textScore",
// }
// paginatedData, err := paginate.New(collection).Context(ctx).Limit(limit).Page(page).Sort("score", sortValue)...
var products []Product
paginatedData, err := paginate.New(collection).Context(ctx).Limit(limit).Page(page).Sort("price", -1).Sort("qty", -1).Select(projection).Filter(filter).Decode(&products).Find()
var dbConnection *mongo.Database

func main() {
// Establishing mongo db connection
ctx := context.Background()
client, err := mongo.Connect(ctx, options.Client().ApplyURI("mongodb://127.0.0.1:27017/"))
if err != nil {
panic(err)
}
dbConnection = client.Database("myaggregate")
////_, insertErr := insertExamples(client.Database("myaggregate"))
////if insertErr != nil {
//// panic(insertErr)
////}
//
//// Example for Normal Find query
//filter := bson.M{}
//var limit int64 = 10
//var page int64 = 2
//collection := client.Database("myaggregate").Collection("products")
//projection := bson.D{
// {"name", 1},
// {"qty", 1},
//}
//// Querying paginated data
//// If you want to do some complex sort like sort by score(weight) for full text search fields you can do it easily
//// sortValue := bson.M{
//// "$meta" : "textScore",
//// }
//// paginatedData, err := paginate.New(collection).Context(ctx).Limit(limit).Page(page).Sort("score", sortValue)...
//var products []Product
//paginatedData, err := paginate.New(collection).Context(ctx).Limit(limit).Page(page).Sort("price", -1).Sort("qty", -1).Select(projection).Filter(filter).Decode(&products).Find()
//if err != nil {
// panic(err)
//}
//fmt.Println(paginatedData)
//res, _ := json.Marshal(paginatedData)
//fmt.Println(string(res))
//// paginated data is in paginatedData.Data
//// pagination info can be accessed in paginatedData.Pagination
////// if you want to marshal data to your defined struct
//// print ProductList
//fmt.Printf("Norm Find Data: %+v\n", products)
//
//// print pagination data
//fmt.Printf("Normal find pagination info: %+v\n", paginatedData.Pagination)
//
////Example for Aggregation
//
////match query
//match := bson.M{"$match": bson.M{"qty": bson.M{"$gt": 10}}}
//
////group query
//projectQuery := bson.M{"$project": bson.M{"_id": 1, "qty": 1}}
//
//// you can easily chain function and pass multiple query like here we are passing match
//// query and projection query as params in Aggregate function you cannot use filter with Aggregate
//// because you can pass filters directly through Aggregate param
//aggPaginatedData, err := paginate.New(collection).Context(ctx).Limit(limit).Page(page).Sort("price", -1).Aggregate(match, projectQuery)
//if err != nil {
// panic(err)
//}
//
//var aggProductList []Product
//for _, raw := range aggPaginatedData.Data {
// var product *Product
// if marshallErr := bson.Unmarshal(raw, &product); marshallErr == nil {
// aggProductList = append(aggProductList, *product)
// }
//
//}
//
//// print ProductList
//fmt.Printf("Aggregate Product List: %+v\n", aggProductList)
//
//// print pagination data
//fmt.Printf("Aggregate Pagination Data: %+v\n", aggPaginatedData.Pagination)

// paginated data is in paginatedData.Data
// pagination info can be accessed in paginatedData.Pagination
//// if you want to marshal data to your defined struct
// print ProductList
fmt.Printf("Norm Find Data: %+v\n", products)

// print pagination data
fmt.Printf("Normal find pagination info: %+v\n", paginatedData.Pagination)

//Example for Aggregation

//match query
match := bson.M{"$match": bson.M{"qty": bson.M{"$gt": 10}}}
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Testing pagination go to http://localhost:8081/normal-pagination?page=1&limit=10 to beign testing")
})

//group query
projectQuery := bson.M{"$project": bson.M{"_id": 1, "qty": 1}}
http.HandleFunc("/normal-pagination", func(w http.ResponseWriter, r *http.Request) {
convertedPageInt, convertedLimitInt := getPageAndLimit(r)
// Example for Normal Find query
filter := bson.M{}
limit := int64(convertedLimitInt)
page := int64(convertedPageInt)
collection := dbConnection.Collection("products")
projection := bson.D{
{"name", 1},
{"qty", 1},
}
// Querying paginated data
// If you want to do some complex sort like sort by score(weight) for full text search fields you can do it easily
// sortValue := bson.M{
// "$meta" : "textScore",
// }
// paginatedData, err := paginate.New(collection).Context(ctx).Limit(limit).Page(page).Sort("score", sortValue)...
var products []Product
paginatedData, err := paginate.New(collection).Context(ctx).Limit(limit).Page(page).Sort("price", -1).Sort("qty", -1).Select(projection).Filter(filter).Decode(&products).Find()
if err != nil {
panic(err)
}

// you can easily chain function and pass multiple query like here we are passing match
// query and projection query as params in Aggregate function you cannot use filter with Aggregate
// because you can pass filters directly through Aggregate param
aggPaginatedData, err := paginate.New(collection).Context(ctx).Limit(limit).Page(page).Sort("price", -1).Aggregate(match, projectQuery)
if err != nil {
panic(err)
}
payload := struct {
Data []Product `json:"data"`
Pagination paginate.PaginationData `json:"pagination"`
}{
Pagination: paginatedData.Pagination,
Data: products,
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(payload)
})

http.HandleFunc("/aggregate-pagination", func(w http.ResponseWriter, r *http.Request) {
convertedPageInt, convertedLimitInt := getPageAndLimit(r)
collection := dbConnection.Collection("products")

var aggProductList []Product
for _, raw := range aggPaginatedData.Data {
var product *Product
if marshallErr := bson.Unmarshal(raw, &product); marshallErr == nil {
aggProductList = append(aggProductList, *product)
//Example for Aggregation
limit := int64(convertedLimitInt)
page := int64(convertedPageInt)
//match query
match := bson.M{"$match": bson.M{"price": bson.M{"$gt": 0}}}
//
//group query
projectQuery := bson.M{"$project": bson.M{"_id": 1, "name": 1, "qty": 1}}

// you can easily chain function and pass multiple query like here we are passing match
// query and projection query as params in Aggregate function you cannot use filter with Aggregate
// because you can pass filters directly through Aggregate param
aggPaginatedData, err := paginate.New(collection).Context(ctx).Limit(limit).Page(page).Sort("price", -1).Aggregate( match,projectQuery)
if err != nil {
panic(err)
}

var aggProductList []Product
for _, raw := range aggPaginatedData.Data {
var product *Product
if marshallErr := bson.Unmarshal(raw, &product); marshallErr == nil {
aggProductList = append(aggProductList, *product)
}

}

payload := struct {
Data []Product `json:"data"`
Pagination paginate.PaginationData `json:"pagination"`
}{
Pagination: aggPaginatedData.Pagination,
Data: aggProductList,
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(payload)
})

fmt.Println("Application started on port http://localhost:8081")
log.Fatal(http.ListenAndServe(":8081", nil))
}

func getPageAndLimit(r *http.Request) (convertedPageInt int, convertedLimitInt int) {
queryPageValue := r.FormValue("page")
if queryPageValue != "" {
convertedPageInt, _ = strconv.Atoi(queryPageValue)
}

// print ProductList
fmt.Printf("Aggregate Product List: %+v\n", aggProductList)
queryLimitValue := r.FormValue("limit")
if queryLimitValue != "" {
convertedLimitInt, _ = strconv.Atoi(queryLimitValue)
}

// print pagination data
fmt.Printf("Aggregate Pagination Data: %+v\n", aggPaginatedData.Pagination)
return convertedPageInt, convertedLimitInt
}

0 comments on commit d16b35a

Please sign in to comment.