golang实现MongoDB分页查询与聚合管道支持的插件库mongo-go-pagination的使用

Golang实现MongoDB分页查询与聚合管道支持的插件库mongo-go-pagination的使用

安装

$ go get -u -v github.com/gobeam/mongo-go-pagination

或者使用dep:

$ dep ensure -add github.com/gobeam/mongo-go-pagination

聚合管道查询示例

package main

import (
	"context"
	"fmt"
	. "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"
)

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"`
}

func main() {
	// 建立MongoDB连接
	ctx, _ := context.WithTimeout(context.Background(), 10*time.Second)
	client, err := mongo.Connect(ctx, options.Client().ApplyURI("mongodb://localhost:27017"))
	if err != nil {
		panic(err)
	}
	
	var limit int64 = 10
	var page int64 = 1
	collection := client.Database("myaggregate").Collection("stocks")

	// 聚合查询示例

	// 匹配查询
	match := bson.M{"$match": bson.M{"qty": bson.M{"$gt": 10}}}

	// 投影查询
	projectQuery := bson.M{"$project": bson.M{"_id": 1, "qty": 1}}

    // 设置collation(可选)
    collation := options.Collation{
		Locale:    "en",
		CaseLevel: true,
	}

	// 可以链式调用函数并传递多个查询参数
	// 这里我们传递了match查询和projection查询作为Aggregate函数的参数
	aggPaginatedData, err := New(collection).SetCollation(&collation).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)
		}
	}

	// 打印产品列表
	fmt.Printf("Aggregate Product List: %+v\n", aggProductList)

	// 打印分页数据
	fmt.Printf("Aggregate Pagination Data: %+v\n", aggPaginatedData.Data)
}

普通查询示例

func main() {
	// 建立MongoDB连接
	ctx, _ := context.WithTimeout(context.Background(), 10*time.Second)
	client, err := mongo.Connect(ctx, options.Client().ApplyURI("mongodb://localhost:27017"))
	if err != nil {
		panic(err)
	}

	// 普通查询示例
    	filter := bson.M{}
    	var limit int64 = 10
    	var page int64 = 1
    	collection := client.Database("myaggregate").Collection("stocks")
    	projection := bson.D{
    		{"name", 1},
    		{"qty", 1},
    	}
    	
        var products []Product
    	paginatedData, err := New(collection).Context(ctx).Limit(limit).Page(page).Sort("price", -1).Select(projection).Filter(filter).Decode(&products).Find()
    	if err != nil {
    		panic(err)
    	}
    
    	// paginatedData.Data将为nil,因为数据已通过Decode函数解码
    	// 分页信息可以在paginatedData.Pagination中访问
    	// 打印产品列表
    	fmt.Printf("Normal Find Data: %+v\n", products)
    
    	// 打印分页数据
    	fmt.Printf("Normal find pagination info: %+v\n", paginatedData.Pagination)
}

注意:

paginatedData.data // 对于普通查询,它将是nil,因为数据已通过Decode函数解码

运行测试

$ go test

贡献

欢迎提交Pull Request。对于重大更改,请先提出问题以讨论您希望更改的内容。

请确保适当更新测试。

许可证

MIT License

Copyright (c) 2021

更多关于golang实现MongoDB分页查询与聚合管道支持的插件库mongo-go-pagination的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang实现MongoDB分页查询与聚合管道支持的插件库mongo-go-pagination的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


使用 mongo-go-pagination 实现 MongoDB 分页查询与聚合管道

mongo-go-pagination 是一个专门为 Go 语言 MongoDB 驱动设计的轻量级分页库,它支持基本查询和聚合管道的分页功能。下面我将详细介绍如何使用这个库。

安装

首先安装 mongo-go-pagination 库:

go get github.com/gobeam/mongo-go-pagination

基本查询分页

package main

import (
	"context"
	"fmt"
	"log"
	"time"

	"github.com/gobeam/mongo-go-pagination"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/mongo"
	"go.mongodb.org/mongo-driver/mongo/options"
)

type Product struct {
	Name      string    `bson:"name"`
	Price     float64   `bson:"price"`
	CreatedAt time.Time `bson:"created_at"`
}

func main() {
	// 连接 MongoDB
	client, err := mongo.Connect(context.Background(), options.Client().ApplyURI("mongodb://localhost:27017"))
	if err != nil {
		log.Fatal(err)
	}
	defer client.Disconnect(context.Background())

	collection := client.Database("testdb").Collection("products")

	// 创建一些测试数据
	createTestData(collection)

	// 基本查询分页
	basicPagination(collection)
}

func createTestData(collection *mongo.Collection) {
	// 这里可以插入一些测试数据
	// ...
}

func basicPagination(collection *mongo.Collection) {
	filter := bson.M{"price": bson.M{"$gt": 10}} // 查询条件

	// 第1页,每页5条记录
	paginatedData, err := pagination.New(collection).Limit(5).Page(1).Filter(filter).Find()
	if err != nil {
		log.Fatal(err)
	}

	// 解码结果
	var products []Product
	for _, raw := range paginatedData.Data {
		var product Product
		if err := bson.Unmarshal(raw, &product); err != nil {
			log.Fatal(err)
		}
		products = append(products, product)
	}

	fmt.Printf("Total Records: %d\n", paginatedData.Pagination.Total)
	fmt.Printf("Page: %d\n", paginatedData.Pagination.Page)
	fmt.Printf("Per Page: %d\n", paginatedData.Pagination.PerPage)
	fmt.Printf("Total Pages: %d\n", paginatedData.Pagination.TotalPage)
	fmt.Println("Products:")
	for _, p := range products {
		fmt.Printf("- %s: $%.2f\n", p.Name, p.Price)
	}
}

聚合管道分页

func aggregatePagination(collection *mongo.Collection) {
	// 定义聚合管道
	pipeline := []bson.M{
		{
			"$match": bson.M{
				"price": bson.M{"$gt": 10},
			},
		},
		{
			"$group": bson.M{
				"_id":   "$category",
				"count": bson.M{"$sum": 1},
				"total": bson.M{"$sum": "$price"},
			},
		},
		{
			"$sort": bson.M{"total": -1},
		},
	}

	// 第1页,每页3条记录
	paginatedData, err := pagination.New(collection).Limit(3).Page(1).Aggregate(pipeline)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Printf("\nAggregation Results (Page %d):\n", paginatedData.Pagination.Page)
	for _, raw := range paginatedData.Data {
		var result struct {
			ID    string  `bson:"_id"`
			Count int     `bson:"count"`
			Total float64 `bson:"total"`
		}
		if err := bson.Unmarshal(raw, &result); err != nil {
			log.Fatal(err)
		}
		fmt.Printf("- Category: %s, Count: %d, Total: $%.2f\n", result.ID, result.Count, result.Total)
	}
}

高级功能

1. 排序

// 添加排序条件
paginatedData, err := pagination.New(collection).
    Limit(5).
    Page(1).
    Sort("price", -1). // -1 表示降序
    Filter(filter).
    Find()

2. 选择字段

// 只选择特定字段
paginatedData, err := pagination.New(collection).
    Limit(5).
    Page(1).
    Select(bson.M{"name": 1, "price": 1}).
    Filter(filter).
    Find()

3. 自定义解码

// 自定义解码方式
var products []Product
paginatedData, err := pagination.New(collection).
    Limit(5).
    Page(1).
    Filter(filter).
    Decode(&products)

性能考虑

  1. 对于大型集合,确保查询字段有适当的索引
  2. 避免在分页查询中使用 $where 或 JavaScript 表达式
  3. 考虑使用 hint() 强制使用特定索引

总结

mongo-go-pagination 提供了简单易用的 API 来实现 MongoDB 分页功能,主要特点包括:

  • 支持基本查询和聚合管道的分页
  • 提供丰富的分页元数据(总记录数、总页数等)
  • 灵活的排序和字段选择
  • 与官方 MongoDB Go 驱动无缝集成

对于大多数分页需求,这个库都能提供简洁高效的解决方案。

回到顶部