欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

go?mongox簡(jiǎn)潔高效文檔操作及bson數(shù)據(jù)構(gòu)造流暢技巧

 更新時(shí)間:2023年11月16日 09:49:38   作者:陳明勇  
這篇文章主要為大家介紹了go?mongox簡(jiǎn)潔高效文檔操作及bson數(shù)據(jù)構(gòu)造流暢技巧示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

前言

在 Go 語(yǔ)言中使用 MongoDB 官方框架進(jìn)行集合操作時(shí),深深感到構(gòu)建 bson 數(shù)據(jù)是一件非常繁瑣的工作。字段、逗號(hào),括號(hào)等符號(hào)的排列,讓我感覺(jué)仿佛是在進(jìn)行一場(chǎng)拼圖游戲。

因此我在想,有沒(méi)有一個(gè)能讓我絲滑,高效操作 MongoDB 的第三方框架呢,遺憾的是,并沒(méi)有找到符合我預(yù)期的框架,索性我就自己動(dòng)手開(kāi)發(fā)了一個(gè),這就是 go-mongox 框架的由來(lái)。

如果你也有類(lèi)似我的這種感受,相信 go-mongox 框架能給你帶來(lái)不一樣的體驗(yàn)。

go-mongox

go-mongox 基于 泛型 對(duì) MongoDB 官方框架進(jìn)行了二次封裝,它通過(guò)使用鏈?zhǔn)秸{(diào)用的方式,讓我們能夠絲滑地操作文檔。同時(shí),其還提供了多種類(lèi)型的 bson 構(gòu)造器,幫助我們高效的構(gòu)建 bson 數(shù)據(jù)。

倉(cāng)庫(kù)地址:https://github.com/chenmingyong0423/go-mongox

該框架處于初期階段,希望通過(guò)集思廣益的方式,邀請(qǐng)各位開(kāi)發(fā)者共同參與,提出寶貴的建議和意見(jiàn),共同打造一個(gè)更強(qiáng)大、更靈活的框架。期待著您的積極參與和寶貴反饋,共同推動(dòng)go-mongox不斷進(jìn)步。

功能

  • 文檔的 crud 操作
  • 聚合操作
  • 構(gòu)造 bson 數(shù)據(jù)
  • ······(敬請(qǐng)期待)

安裝

go get github.com/chenmingyong0423/go-mongox@latest

collection 集合操作

基于泛型的 collection 形態(tài)初始化

package main
import (
    "context"
    "github.com/chenmingyong0423/go-mongox"
    "go.mongodb.org/mongo-driver/mongo"
    "go.mongodb.org/mongo-driver/mongo/options"
    "go.mongodb.org/mongo-driver/mongo/readpref"
)
type Post struct {
    Id      string `bson:"_id"`
    Title   string `bson:"title"`
    Author  string `bson:"author"`
    Content string `bson:"content"`
}
func main() {
    // 你需要預(yù)先創(chuàng)建一個(gè) *mongo.Collection 對(duì)象
    mongoCollection := newCollection()
    // 使用 Post 結(jié)構(gòu)體作為泛型參數(shù)創(chuàng)建一個(gè) collection
    postCollection := mongox.NewCollection[Post](mongoCollection)
}
// 示例代碼,不是最佳的創(chuàng)建方式
func newCollection() *mongo.Collection {
    client, err := mongo.Connect(context.Background(), options.Client().ApplyURI("mongodb://localhost:27017").SetAuth(options.Credential{
        Username:   "test",
        Password:   "test",
        AuthSource: "db-test",
    }))
    if err != nil {
        panic(err)
    }
    err = client.Ping(context.Background(), readpref.Primary())
    if err != nil {
        panic(err)
    }
    collection := client.Database("db-test").Collection("test_post")
    return collection
}

通過(guò) mongox.NewCollection 函數(shù),我們可以創(chuàng)建一個(gè)基于泛型的 collection 裝飾器。

Creator 創(chuàng)造器

Creator 是一個(gè)創(chuàng)造器,用于執(zhí)行插入相關(guān)的操作。

插入單個(gè)文檔

// https://github.com/chenmingyong0423/blog/blob/master/tutorial-code/go-mongox/collection/creator/insert_one.go
package main
import (
    "chenmingyong0423/blog/tutorial-code/go-mongox/collection"
    "context"
    "fmt"
    "github.com/chenmingyong0423/go-mongox"
    "go.mongodb.org/mongo-driver/mongo/options"
)
func main() {
    // 你需要預(yù)先創(chuàng)建一個(gè) *mongo.Collection 對(duì)象
    mongoCollection := collection.NewCollection()
    // 使用 Post 結(jié)構(gòu)體作為泛型參數(shù)創(chuàng)建一個(gè) collection
    postCollection := mongox.NewCollection[collection.Post](mongoCollection)
    // 插入一個(gè)文檔
    doc := collection.Post{Id: "1", Title: "go-mongox", Author: "陳明勇", Content: "go-mongox,不一樣的體驗(yàn)。"}
    oneResult, err := postCollection.Creator().InsertOne(context.Background(), doc)
    if err != nil {
        panic(err)
    }
    fmt.Println(oneResult.InsertedID.(string) == "1") // true
    // 攜帶 option 參數(shù)
    oneResult, err = postCollection.Creator().OneOptions(options.InsertOne().SetComment("test")).InsertOne(context.Background(), collection.Post{Id: "2", Title: "go 語(yǔ)言 go-mongox 庫(kù)的使用教程", Author: "陳明勇", Content: "go-mongox 旨在提供更方便和高效的MongoDB數(shù)據(jù)操作體驗(yàn)。"})
    if err != nil {
        panic(err)
    }
    fmt.Println(oneResult.InsertedID.(string) == "2") // true
}

基于 postCollection 實(shí)例,我們可以通過(guò) Creator() 方法創(chuàng)建一個(gè)創(chuàng)造器,然后進(jìn)行插入操作。

InsertOne 方法與官方的 API 同名,作用是插入一條數(shù)據(jù)。如果我們想要設(shè)置 options 參數(shù),應(yīng)使用 OneOptions 方法。

可以看到,無(wú)論是設(shè)置 options 參數(shù)還是執(zhí)行插入操作,都在一條鏈路上完成,即實(shí)現(xiàn)了鏈?zhǔn)讲僮鳌?/p>

插入多個(gè)文檔

// https://github.com/chenmingyong0423/blog/blob/master/tutorial-code/go-mongox/collection/creator/insert_many.go
package main
import (
    "chenmingyong0423/blog/tutorial-code/go-mongox/collection"
    "context"
    "fmt"
    "github.com/chenmingyong0423/go-mongox"
    "go.mongodb.org/mongo-driver/mongo/options"
)
func main() {
    // 你需要預(yù)先創(chuàng)建一個(gè) *mongo.Collection 對(duì)象
    mongoCollection := collection.NewCollection()
    // 使用 Post 結(jié)構(gòu)體作為泛型參數(shù)創(chuàng)建一個(gè) collection
    postCollection := mongox.NewCollection[collection.Post](mongoCollection)
    docs := []collection.Post{
        {Id: "1", Title: "go", Author: "陳明勇", Content: "..."},
        {Id: "2", Title: "mongo", Author: "陳明勇", Content: "..."},
    }
    manyResult, err := postCollection.Creator().InsertMany(context.Background(), docs)
    if err != nil {
        panic(err)
    }
    fmt.Println(len(manyResult.InsertedIDs) == 2) // true
    // 攜帶 option 參數(shù)
    manyResult, err = postCollection.Creator().ManyOptions(options.InsertMany().SetComment("test")).InsertMany(context.Background(), []collection.Post{
        {Id: "3", Title: "go-mongox", Author: "陳明勇", Content: "..."},
        {Id: "4", Title: "builder", Author: "陳明勇", Content: "..."},
    })
    if err != nil {
        panic(err)
    }
    fmt.Println(len(manyResult.InsertedIDs) == 2) // true
}

InsertMany 方法與官方的 API 同名,作用是插入多條數(shù)據(jù)。如果我們想要設(shè)置 options 參數(shù),應(yīng)使用 ManyOptions 方法。

Finder 查詢(xún)器

Finder 是一個(gè)查詢(xún)器,用于執(zhí)行查詢(xún)相關(guān)的操作。

查詢(xún)單個(gè)文檔

// https://github.com/chenmingyong0423/blog/blob/master/tutorial-code/go-mongox/collection/finder/find_one.go
package main
import (
    "chenmingyong0423/blog/tutorial-code/go-mongox/collection"
    "context"
    "fmt"
    "github.com/chenmingyong0423/go-mongox"
    "github.com/chenmingyong0423/go-mongox/bsonx"
    "github.com/chenmingyong0423/go-mongox/builder/query"
    "go.mongodb.org/mongo-driver/mongo/options"
)
func main() {
    // 你需要預(yù)先創(chuàng)建一個(gè) *mongo.Collection 對(duì)象
    mongoCollection := collection.NewCollection()
    // 使用 Post 結(jié)構(gòu)體作為泛型參數(shù)創(chuàng)建一個(gè) collection
    postCollection := mongox.NewCollection[collection.Post](mongoCollection)
    _, err := postCollection.Creator().InsertOne(context.Background(), collection.Post{Id: "1", Title: "go", Author: "陳明勇", Content: "..."})
    if err != nil {
        panic(err)
    }
    // 查詢(xún)單個(gè)文檔
    post, err := postCollection.Finder().Filter(bsonx.Id("1")).FindOne(context.Background())
    if err != nil {
        panic(err)
    }
    fmt.Println(post)
    // 設(shè)置 *options.FindOneOptions 參數(shù)
    post2, err := postCollection.Finder().
        Filter(bsonx.Id("1")).
        OneOptions(options.FindOne().SetProjection(bsonx.M("content", 0))).
        FindOne(context.Background())
    if err != nil {
        panic(err)
    }
    fmt.Println(post2)
    // - map 作為 filter 條件
    post3, err := postCollection.Finder().Filter(map[string]any{"_id": "1"}).FindOne(context.Background())
    if err != nil {
        panic(err)
    }
    fmt.Println(post3)
    // - 復(fù)雜條件查詢(xún)
    // -- 使用 query 包構(gòu)造復(fù)雜的 bson: bson.D{bson.E{Key: "title", Value: bson.M{"$eq": "go"}}, bson.E{Key: "author", Value: bson.M{"$eq": "陳明勇"}}}
    post4, err := postCollection.Finder().
        Filter(query.BsonBuilder().Eq("title", "go").Eq("author", "陳明勇").Build()).
        FindOne(context.Background())
    if err != nil {
        panic(err)
    }
    fmt.Println(post4)
}

基于 postCollection 實(shí)例,我們可以通過(guò) Finder() 方法創(chuàng)建一個(gè)查詢(xún)器,然后進(jìn)行查詢(xún)操作。

FindOne 方法與官方的 API 同名,作用是查詢(xún)單個(gè)文檔。我們可以通過(guò) Filter 和 OneOptions 方法分別設(shè)置 查詢(xún)條件 和 options 參數(shù)。

對(duì)于簡(jiǎn)單的查詢(xún)條件,我們可以使用 bsonx 包提供的函數(shù)進(jìn)行構(gòu)造,例如 bsonx.Id("1");對(duì)于復(fù)雜的查詢(xún)條件,我們可以使用 query 包提供的 BsonBuilder構(gòu)造器進(jìn)行構(gòu)造。這兩個(gè)包的用法接下來(lái)會(huì)進(jìn)行詳細(xì)地介紹。

查詢(xún)多個(gè)文檔

// https://github.com/chenmingyong0423/blog/blob/master/tutorial-code/go-mongox/collection/finder/find.go
package main

import (
    "chenmingyong0423/blog/tutorial-code/go-mongox/collection"
    "context"
    "fmt"

    "github.com/chenmingyong0423/go-mongox"
    "github.com/chenmingyong0423/go-mongox/bsonx"
    "github.com/chenmingyong0423/go-mongox/builder/query"
    "go.mongodb.org/mongo-driver/mongo/options"
)

func main() {
    // 你需要預(yù)先創(chuàng)建一個(gè) *mongo.Collection 對(duì)象
    mongoCollection := collection.NewCollection()
    // 使用 Post 結(jié)構(gòu)體作為泛型參數(shù)創(chuàng)建一個(gè) collection
    postCollection := mongox.NewCollection[collection.Post](mongoCollection)
    _, err := postCollection.Creator().InsertMany(context.Background(), []collection.Post{
        {Id: "1", Title: "go", Author: "陳明勇", Content: "..."},
        {Id: "2", Title: "mongo", Author: "陳明勇", Content: "..."},
    })
    if err != nil {
        panic(err)
    }

    // 查詢(xún)多個(gè)文檔
    // bson.D{bson.E{Key: "_id", Value: bson.M{"$in": []string{"1", "2"}}}}
    posts, err := postCollection.Finder().Filter(query.BsonBuilder().InString("_id", []string{"1", "2"}...).Build()).Find(context.Background())
    if err != nil {
        panic(err)
    }
    for _, post := range posts {
        fmt.Println(post)
    }

    // 設(shè)置 *options.FindOptions 參數(shù)
    // bson.D{bson.E{Key: "_id", Value: bson.M{types.In: []string{"1", "2"}}}}
    posts2, err := postCollection.Finder().
        Filter(query.BsonBuilder().InString("_id", []string{"1", "2"}...).Build()).
        Options(options.Find().SetProjection(bsonx.M("content", 0))).
        Find(context.Background())
    if err != nil {
        panic(err)
    }
    for _, post := range posts2 {
        fmt.Println(post)
    }
}

Find 方法與官方的 API 同名,作用是查詢(xún)多個(gè)文檔。如果我們想要設(shè)置 options 參數(shù),應(yīng)使用 Options 方法。

在上面的例子中,為了構(gòu)造 $in 查詢(xún)語(yǔ)句,我們使用了 BsonBuilder 提供的方法 InString。

Updater 更新器

Updater 是一個(gè)更新器,用于執(zhí)行更新相關(guān)的操作。

更新單個(gè)文檔

// https://github.com/chenmingyong0423/blog/blob/master/tutorial-code/go-mongox/collection/updater/update_one.go
package main

import (
    "chenmingyong0423/blog/tutorial-code/go-mongox/collection"
    "context"
    "fmt"

    "github.com/chenmingyong0423/go-mongox"
    "github.com/chenmingyong0423/go-mongox/bsonx"
    "github.com/chenmingyong0423/go-mongox/builder/update"
    "github.com/chenmingyong0423/go-mongox/types"
    "go.mongodb.org/mongo-driver/mongo/options"
)

func main() {
    // 你需要預(yù)先創(chuàng)建一個(gè) *mongo.Collection 對(duì)象
    mongoCollection := collection.NewCollection()
    // 使用 Post 結(jié)構(gòu)體作為泛型參數(shù)創(chuàng)建一個(gè) collection
    postCollection := mongox.NewCollection[collection.Post](mongoCollection)
    _, err := postCollection.Creator().InsertOne(context.Background(), collection.Post{Id: "1", Title: "go", Author: "陳明勇", Content: "..."})
    if err != nil {
        panic(err)
    }

    // 更新單個(gè)文檔
    // 通過(guò) update 包構(gòu)建 bson 更新語(yǔ)句
    updateResult, err := postCollection.Updater().
        Filter(bsonx.Id("1")).
        Updates(update.BsonBuilder().Set(bsonx.M("title", "golang")).Build()).
        UpdateOne(context.Background())
    if err != nil {
        panic(err)
    }
    fmt.Println(updateResult.ModifiedCount == 1) // true

    // - 使用 map 構(gòu)造更新數(shù)據(jù),并設(shè)置 *options.UpdateOptions,執(zhí)行 upsert 操作
    updateResult2, err := postCollection.Updater().
        Filter(bsonx.Id("2")).
        UpdatesWithOperator(types.Set, map[string]any{"title": "mongo"}).Options(options.Update().SetUpsert(true)).
        UpdateOne(context.Background())
    if err != nil {
        panic(err)
    }
    fmt.Println(updateResult2.UpsertedID.(string) == "2") // true
}

基于 postCollection 實(shí)例,我們可以通過(guò) Updater() 方法創(chuàng)建一個(gè)更新器,然后進(jìn)行更新操作。

UpdateOne 方法與官方的 API 同名,作用是更新單個(gè)文檔。我們可以通過(guò) Filter 和 Options 方法分別設(shè)置 文檔匹配的條件 和 options 參數(shù)。

對(duì)于更新操作參數(shù),我們可以使用以下兩個(gè)方法進(jìn)行設(shè)置:

  • Updates 方法:該方法接收 bson 或 map 等合法的更新操作語(yǔ)句。上面的例子使用了 update 包里的 BsonBuilder 對(duì)更新操作語(yǔ)句進(jìn)行構(gòu)造。
  • UpdatesWithOperator 方法:該方法的第一個(gè)參數(shù)為更新操作符,第二個(gè)參數(shù)為預(yù)期更新的數(shù)據(jù)。

更新多個(gè)文檔

// https://github.com/chenmingyong0423/blog/blob/master/tutorial-code/go-mongox/collection/updater/update_many.go
package main

import (
    "chenmingyong0423/blog/tutorial-code/go-mongox/collection"
    "context"
    "fmt"

    "github.com/chenmingyong0423/go-mongox"
    "github.com/chenmingyong0423/go-mongox/bsonx"
    "github.com/chenmingyong0423/go-mongox/builder/query"
    "github.com/chenmingyong0423/go-mongox/builder/update"
)

func main() {
    // 你需要預(yù)先創(chuàng)建一個(gè) *mongo.Collection 對(duì)象
    mongoCollection := collection.NewCollection()
    // 使用 Post 結(jié)構(gòu)體作為泛型參數(shù)創(chuàng)建一個(gè) collection
    postCollection := mongox.NewCollection[collection.Post](mongoCollection)
    _, err := postCollection.Creator().InsertMany(context.Background(), []collection.Post{
        {Id: "1", Title: "go", Author: "陳明勇", Content: "..."},
        {Id: "2", Title: "mongo", Author: "陳明勇", Content: "..."},
    })
    if err != nil {
        panic(err)
    }

    // 更新多個(gè)文檔
    updateResult, err := postCollection.Updater().
        Filter(query.BsonBuilder().InString("_id", []string{"1", "2"}...).Build()).
        Updates(update.BsonBuilder().Set(bsonx.M("title", "golang")).Build()).
        UpdateMany(context.Background())
    if err != nil {
        panic(err)
    }
    fmt.Println(updateResult.ModifiedCount == 2) // true
}

UpdateMany 方法與官方的 API 同名,作用是更新多個(gè)文檔。

Deleter 刪除器

Deleter 是一個(gè)刪除器,用于執(zhí)行刪除相關(guān)的操作。

刪除單個(gè)文檔

// https://github.com/chenmingyong0423/blog/blob/master/tutorial-code/go-mongox/collection/deleter/delete_one.go
package main

import (
    "chenmingyong0423/blog/tutorial-code/go-mongox/collection"
    "context"
    "fmt"

    "github.com/chenmingyong0423/go-mongox"
    "github.com/chenmingyong0423/go-mongox/bsonx"
    "go.mongodb.org/mongo-driver/mongo/options"
)

func main() {
    // 你需要預(yù)先創(chuàng)建一個(gè) *mongo.Collection 對(duì)象
    mongoCollection := collection.NewCollection()
    // 使用 Post 結(jié)構(gòu)體作為泛型參數(shù)創(chuàng)建一個(gè) collection
    postCollection := mongox.NewCollection[collection.Post](mongoCollection)
    _, err := postCollection.Creator().InsertMany(context.Background(), []collection.Post{
        {Id: "1", Title: "go", Author: "陳明勇", Content: "..."},
        {Id: "2", Title: "mongo", Author: "陳明勇", Content: "..."},
    })
    if err != nil {
        panic(err)
    }

    // 刪除單個(gè)文檔
    deleteResult, err := postCollection.Deleter().Filter(bsonx.Id("1")).DeleteOne(context.Background())
    if err != nil {
        panic(err)
    }
    fmt.Println(deleteResult.DeletedCount == 1) // true

    // 攜帶 option 參數(shù)
    deleteResult2, err := postCollection.Deleter().Filter(bsonx.Id("2")).Options(options.Delete().SetComment("test")).DeleteOne(context.Background())
    if err != nil {
        panic(err)
    }
    fmt.Println(deleteResult2.DeletedCount == 1) // true
}

基于 postCollection 實(shí)例,我們可以通過(guò) Deleter() 方法創(chuàng)建一個(gè)刪除器,然后進(jìn)行刪除操作。

DeleteOne 方法與官方的 API 同名,作用是刪除單個(gè)文檔。我們可以通過(guò) Filter 和 Options 方法分別設(shè)置 文檔匹配的條件 和 options 參數(shù)。

刪除多個(gè)文檔

// https://github.com/chenmingyong0423/blog/blob/master/tutorial-code/go-mongox/collection/deleter/delete_many.go
package main

import (
    "chenmingyong0423/blog/tutorial-code/go-mongox/collection"
    "context"
    "fmt"

    "github.com/chenmingyong0423/go-mongox"
    "github.com/chenmingyong0423/go-mongox/builder/query"
)

func main() {
    // 你需要預(yù)先創(chuàng)建一個(gè) *mongo.Collection 對(duì)象
    mongoCollection := collection.NewCollection()
    // 使用 Post 結(jié)構(gòu)體作為泛型參數(shù)創(chuàng)建一個(gè) collection
    postCollection := mongox.NewCollection[collection.Post](mongoCollection)
    _, err := postCollection.Creator().InsertMany(context.Background(), []collection.Post{
       {Id: "1", Title: "go", Author: "陳明勇", Content: "..."},
       {Id: "2", Title: "mongo", Author: "陳明勇", Content: "..."},
    })
    if err != nil {
       panic(err)
    }

    // 刪除多個(gè)文檔
    // - 通過(guò) query 包構(gòu)造復(fù)雜的 bson 語(yǔ)句
    deleteResult, err := postCollection.Deleter().Filter(query.BsonBuilder().InString("_id", []string{"1", "2"}...).Build()).DeleteMany(context.Background())
    if err != nil {
       panic(err)
    }
    fmt.Println(deleteResult.DeletedCount == 2) // true
}

DeleteMany 方法與官方的 API 同名,作用是刪除多個(gè)文檔。

Aggregator 聚合器

Aggregator 是一個(gè)聚合器,用于執(zhí)行聚合相關(guān)的操作。

// https://github.com/chenmingyong0423/blog/blob/master/tutorial-code/go-mongox/collection/aggregator/aggregator.go
package main
import (
    "chenmingyong0423/blog/tutorial-code/go-mongox/collection"
    "context"
    "fmt"
    "github.com/chenmingyong0423/go-mongox"
    "github.com/chenmingyong0423/go-mongox/bsonx"
    "github.com/chenmingyong0423/go-mongox/builder/aggregation"
    "github.com/chenmingyong0423/go-mongox/types"
    "go.mongodb.org/mongo-driver/mongo"
)
func main() {
    // 你需要預(yù)先創(chuàng)建一個(gè) *mongo.Collection 對(duì)象
    mongoCollection := collection.NewCollection()
    // 使用 Post 結(jié)構(gòu)體作為泛型參數(shù)創(chuàng)建一個(gè) collection
    postCollection := mongox.NewCollection[collection.Post](mongoCollection)
    _, err := postCollection.Creator().InsertMany(context.Background(), []collection.Post{
        {Id: "1", Title: "go", Author: "陳明勇", Content: "..."},
        {Id: "2", Title: "mongo", Author: "陳明勇", Content: "..."},
    })
    if err != nil {
        panic(err)
    }
    // 聚合操作
    // - 使用 aggregation 包構(gòu)造 pipeline
    posts, err := postCollection.
        Aggregator().Pipeline(aggregation.StageBsonBuilder().Project(bsonx.M("content", 0)).Build()).
        Aggregate(context.Background())
    if err != nil {
        panic(err)
    }
    for _, post := range posts {
        fmt.Println(post)
    }
    // 如果我們通過(guò)聚合操作更改字段的名稱(chēng),那么我們可以使用 AggregationWithCallback 方法,然后通過(guò) callback 函數(shù)將結(jié)果映射到我們預(yù)期的結(jié)構(gòu)體中
    type DiffPost struct {
        Id          string `bson:"_id"`
        Title       string `bson:"title"`
        Name        string `bson:"name"` // author → name
        Content     string `bson:"content"`
        Outstanding bool   `bson:"outstanding"`
    }
    result := make([]*DiffPost, 0)
    //  將 author 字段更名為 name,排除 content 字段,添加 outstanding 字段,返回結(jié)果為 []*DiffPost
    err = postCollection.Aggregator().
        Pipeline(aggregation.StageBsonBuilder().Project(
            bsonx.D(types.KV("name", "$author"), types.KV("author", 1), types.KV("_id", 1), types.KV("title", 1), types.KV("outstanding", aggregation.BsonBuilder().Eq("$author", "陳明勇").Build()))).Build(),
        ).
        AggregateWithCallback(context.Background(), func(ctx context.Context, cursor *mongo.Cursor) error {
            return cursor.All(ctx, &result)
        })
    for _, post := range result {
        fmt.Println(post)
    }
}

基于 postCollection 實(shí)例,我們可以通過(guò) Aggregator() 方法創(chuàng)建一個(gè)聚合器,然后進(jìn)行聚合操作。

我們可以通過(guò) Pipeline 和 AggregateOptions 方法分別設(shè)置 pipeline 和 options 參數(shù)。

對(duì)于執(zhí)行聚合操作,有以下兩個(gè)方法:

  • Aggregate 方法:與與官方的 API 同名。
  • AggregateWithCallback 方法:因?yàn)槲覀冊(cè)趧?chuàng)建 collection 裝飾器時(shí),使用泛型綁定了一個(gè)結(jié)構(gòu)體,如果我們執(zhí)行聚合操作之后,返回的數(shù)據(jù)與所綁定的結(jié)構(gòu)體映射不上,這時(shí)可以使用該方法將結(jié)果映射到指定的結(jié)構(gòu)里。

Builder 構(gòu)造器

go-mongox 框架提供了以下幾種類(lèi)型的構(gòu)造器:

  • universal: 簡(jiǎn)單而又通用的 bson 數(shù)據(jù)構(gòu)造函數(shù)。
  • query: 查詢(xún)構(gòu)造器,用于構(gòu)造查詢(xún)操作所需的 bson 數(shù)據(jù)。
  • update: 更新構(gòu)造器,用于構(gòu)造更新操作所需的 bson 數(shù)據(jù)。
  • aggregation: 聚合操作構(gòu)造器,包含兩種,一種是用于構(gòu)造聚合 stage 階段所需的 bson 數(shù)據(jù),另一種是用于構(gòu)造除了 stage 階段以外的 bson 數(shù)據(jù)。

universal 通用構(gòu)造

我們可以使用 bsonx 包里的一些函數(shù)進(jìn)行 bson 數(shù)據(jù)的構(gòu)造,例如 bsonx.Mbsonx.Id 和 bsonx.D 等等。

// https://github.com/chenmingyong0423/blog/blob/master/tutorial-code/go-mongox/builder/universal.go
package main

import (
    "fmt"

    "github.com/chenmingyong0423/go-mongox/bsonx"
)

func main() {
    // bson.M{"姓名": "陳明勇"}
    m := bsonx.M("姓名", "陳明勇")
    fmt.Printf("%#v\n\n", m)

    // bson.M{"_id": "陳明勇"}
    id := bsonx.Id("陳明勇")
    fmt.Printf("%#v\n\n", id)

    // bson.D{bson.E{Key:"姓名", Value:"陳明勇"}, bson.E{Key:"手機(jī)號(hào)", Value:"1888***1234"}}
    d := bsonx.D(bsonx.KV("姓名", "陳明勇"), bsonx.KV("手機(jī)號(hào)", "1888***1234"))
    fmt.Printf("%#v\n\n", d)

    // bson.E{Key:"姓名", Value:"陳明勇"}
    e := bsonx.E("姓名", "陳明勇")
    fmt.Printf("%#v\n\n", e)

    // bson.A{"陳明勇", "1888***1234"}
    a := bsonx.A("陳明勇", "1888***1234")
    fmt.Printf("%#v", a)
}

bsonx 包暫時(shí)提供了這些構(gòu)造函數(shù),后面會(huì)持續(xù)添加更多有用的函數(shù)。

特別注意的是,使用 bsonx.D 方法構(gòu)造數(shù)據(jù)時(shí),傳入的參數(shù),需要使用 bsonx.KV 方法進(jìn)行傳遞,目的是強(qiáng)約束 key-value 的類(lèi)型。

query 查詢(xún)構(gòu)造器

query 包可以幫我們構(gòu)造出查詢(xún)相關(guān)的 bson 數(shù)據(jù),例如 $in、$gt、$and 等等。

// https://github.com/chenmingyong0423/blog/blob/master/tutorial-code/go-mongox/builder/query.go
package main

import (
    "fmt"

    "github.com/chenmingyong0423/go-mongox/bsonx"
    "github.com/chenmingyong0423/go-mongox/builder/query"
)

func main() {
    // bson.D{bson.E{Key:"姓名", Value:"陳明勇"}}
    d := query.BsonBuilder().Add(bsonx.KV("姓名", "陳明勇")).Build()
    fmt.Printf("%#v\n\n", d)

    // bson.D{bson.E{Key:"age", Value:bson.D{{Key:"$gt", Value:18}, bson.E{Key:"$lt", Value:25}}}}
    d = query.BsonBuilder().Gt("age", 18).Lt("age", 25).Build()
    fmt.Printf("%#v\n\n", d)

    //  bson.D{bson.E{Key:"age", Value:bson.D{{Key:"$in", Value:[]int{18, 19, 20}}}}}
    d = query.BsonBuilder().InInt("age", 18, 19, 20).Build()
    fmt.Printf("%#v\n\n", d)

    // bson.d{bson.E{Key: "$and", Value: []any{bson.D{{Key: "x", Value: bson.D{{Key: "$ne", Value: 0}}}}, bson.D{{Key: "y", Value: bson.D{{Key: "$gt", Value: 0}}}}}}
    d = query.BsonBuilder().And(
        query.BsonBuilder().Ne("x", 0).Build(),
        query.BsonBuilder().Gt("y", 0).Build(),
    ).Build()
    fmt.Printf("%#v\n\n", d)

    // bson.D{bson.E{Key:"qty", Value:bson.D{{Key:"$exists", Value:true}, bson.E{Key:"$nin", Value:[]int{5, 15}}}}}
    d = query.BsonBuilder().Exists("qty", true).NinInt("qty", 5, 15).Build()
    fmt.Printf("%#v\n\n", d)

    // elemMatch
    // bson.D{bson.E{Key: "result", Value: bson.D{bson.E{Key: "$elemMatch", Value: bson.D{bson.E{Key: "$gte", Value: 80}, bson.E{Key: "$lt", Value: 85}}}}}}
    d = query.BsonBuilder().ElemMatch("result", bsonx.D(bsonx.KV("$gte", 80), bsonx.KV("$lt", 85))).Build()
    fmt.Printf("%#v", d)
}

query 包提供的方法不止這些,以上只是列舉出一些典型的例子,還有更多的用法等著你去探索。

update 更新構(gòu)造器

update 包可以幫我們構(gòu)造出更新操作相關(guān)的 bson 數(shù)據(jù),例如 $set、$$inc$push 等等。

// https://github.com/chenmingyong0423/blog/blob/master/tutorial-code/go-mongox/builder/update.go
package main

import (
    "fmt"

    "github.com/chenmingyong0423/go-mongox/bsonx"
    "github.com/chenmingyong0423/go-mongox/builder/update"
)

func main() {
    // bson.D{bson.E{Key:"$set", Value:bson.M{"name":"陳明勇"}}}
    u := update.BsonBuilder().Set(bsonx.M("name", "陳明勇")).Build()
    fmt.Printf("%#v\n\n", u)

    // bson.D{bson.E{Key:"$inc", Value:bson.D{bson.E{Key:"orders", Value:1}, bson.E{Key:"ratings", Value:-1}}}}
    u = update.BsonBuilder().Inc(bsonx.D(bsonx.KV("orders", 1), bsonx.KV("ratings", -1))).Build()
    fmt.Printf("%#v\n\n", u)

    // bson.D{bson.E{Key:"$push", Value:bson.M{"scores":95}}}
    u = update.BsonBuilder().Push(bsonx.M("scores", 95)).Build()
    fmt.Printf("%#v\n\n", u)

    // bson.D{bson.E{Key:"$unset", Value:bson.D{primitive.E{Key:"quantity", Value:""}, bson.E{Key:"instock", Value:""}}}}
    u = update.BsonBuilder().Unset("quantity", "instock").Build()
    fmt.Printf("%#v", u)
}

update 包提供的方法不止這些,以上只是列舉出一些典型的例子,還有更多的用法等著你去探索。

aggregation 聚合構(gòu)造器

aggregation 包提供了兩個(gè) builder

  • StageBsonBuilder:用于構(gòu)造 stage 階段所需的 bson 數(shù)據(jù)
  • BsonBuilder:用于構(gòu)造除了 stage 階段以外的 bson 數(shù)據(jù)。
// https://github.com/chenmingyong0423/blog/blob/master/tutorial-code/go-mongox/builder/aggregation.go
package main
import (
    "fmt"
    "github.com/chenmingyong0423/go-mongox/bsonx"
    "github.com/chenmingyong0423/go-mongox/builder/aggregation"
    "github.com/chenmingyong0423/go-mongox/builder/query"
    "github.com/chenmingyong0423/go-mongox/types"
)
func main() {
    // bson.D{bson.E{Key:"$gt", Value:[]any{"$qty", 250}}}
    gt := aggregation.BsonBuilder().Gt("$qty", 250).Build()
    fmt.Printf("%#v\n\n", gt)
    // mongo.Pipeline{bson.D{bson.E{Key:"$project", Value:bson.D{bson.E{Key:"name", Value:1}, bson.E{Key:"age", Value:1}, bson.E{Key:"qtyGt250", Value:bson.D{bson.E{Key:"$gt", Value:[]interface {}{"$qty", 250}}}}}}}}
    pipeline := aggregation.StageBsonBuilder().Project(bsonx.D(bsonx.KV("name", 1), bsonx.KV("age", 1), bsonx.KV("qtyGt250", gt))).Build()
    fmt.Printf("%#v\n\n", pipeline)
    // bson.D{bson.E{Key:"$or", Value:[]interface {}{bson.D{bson.E{Key:"score", Value:bson.D{bson.E{Key:"$gt", Value:70}, bson.E{Key:"$lt", Value:90}}}}, bson.D{bson.E{Key:"views", Value:bson.D{bson.E{Key:"$gte", Value:90}}}}}}}
    or := aggregation.BsonBuilder().Or(
       query.BsonBuilder().Gt("score", 70).Lt("score", 90).Build(),
       query.BsonBuilder().Gte("views", 90).Build(),
    ).Build()
    fmt.Printf("%#v\n\n", or)
    // mongo.Pipeline{bson.D{bson.E{Key:"$match", Value:bson.D{bson.E{Key:"$or", Value:[]any{bson.D{bson.E{Key:"score", Value:bson.D{bson.E{Key:"$gt", Value:70}, bson.E{Key:"$lt", Value:90}}}}, bson.D{bson.E{Key:"views", Value:bson.D{bson.E{Key:"$gte", Value:90}}}}}}}}}, bson.D{bson.E{Key:"$group", Value:bson.D{bson.E{Key:"_id", Value:any(nil)}, bson.E{Key:"count", Value:bson.D{bson.E{Key:"$sum", Value:1}}}}}}}
    pipeline = aggregation.StageBsonBuilder().Match(or).Group(nil, bsonx.E("count", aggregation.BsonBuilder().Sum(1).Build())).Build()
    fmt.Printf("%#v\n\n", pipeline)
    // mongo.Pipeline{bson.D{bson.E{Key:"$unwind", Value:"$size"}}}
    pipeline = aggregation.StageBsonBuilder().Unwind("$size", nil).Build()
    fmt.Printf("%#v\n\n", pipeline)
    // mongo.Pipeline{bson.D{bson.E{Key:"$unwind", Value:bson.D{bson.E{Key:"path", Value:"$size"}, bson.E{Key:"includeArrayIndex", Value:"arrayIndex"}, bson.E{Key:"preserveNullAndEmptyArrays", Value:true}}}}}
    pipeline = aggregation.StageBsonBuilder().Unwind("$size", &types.UnWindOptions{
       IncludeArrayIndex:          "arrayIndex",
       PreserveNullAndEmptyArrays: true,
    }).Build()
    fmt.Printf("%#v", pipeline)
}

aggregation 包提供的方法不止這些,以上只是列舉出一些典型的例子,還有更多的用法等著你去探索。

小結(jié)

本文對(duì) go-mongox 框架進(jìn)行了詳細(xì)的介紹,它有兩個(gè)核心,一個(gè)是基于泛型的 colletion 形態(tài),另一個(gè)就是 bson 構(gòu)造器了。這兩個(gè)核心是單獨(dú)存在的,你可以使用其中之一,也可以同時(shí)使用。

倉(cāng)庫(kù)地址:https://github.com/chenmingyong0423/go-mongox

該框架處于初期階段,希望通過(guò)集思廣益的方式,邀請(qǐng)各位開(kāi)發(fā)者共同參與,提出寶貴的建議和意見(jiàn),共同打造一個(gè)更強(qiáng)大、更靈活的框架。期待著您的積極參與和寶貴反饋,共同推動(dòng)go-mongox不斷進(jìn)步。

以上就是go mongox簡(jiǎn)潔高效文檔操作及bson數(shù)據(jù)構(gòu)造流暢技巧的詳細(xì)內(nèi)容,更多關(guān)于go mongox文檔操作bson構(gòu)造的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • gorm golang 并發(fā)連接數(shù)據(jù)庫(kù)報(bào)錯(cuò)的解決方法

    gorm golang 并發(fā)連接數(shù)據(jù)庫(kù)報(bào)錯(cuò)的解決方法

    今天小編就為大家分享一篇gorm golang 并發(fā)連接數(shù)據(jù)庫(kù)報(bào)錯(cuò)的解決方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-07-07
  • 詳解golang中的method

    詳解golang中的method

    這篇文章主要介紹了golang中的method的相關(guān)資料,幫助大家更好的理解和使用golang,感興趣的朋友可以了解下
    2021-01-01
  • Golang?使用os?庫(kù)的?ReadFile()?讀文件最佳實(shí)踐

    Golang?使用os?庫(kù)的?ReadFile()?讀文件最佳實(shí)踐

    這篇文章主要介紹了Golang使用os庫(kù)的ReadFile()讀文件最佳實(shí)踐,文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-09-09
  • Golang中處理import自定義包出錯(cuò)問(wèn)題的解決辦法

    Golang中處理import自定義包出錯(cuò)問(wèn)題的解決辦法

    最近開(kāi)始使用Go/GoLand在import自定義包時(shí)出現(xiàn)各種狀況,下面這篇文章主要給大家介紹了關(guān)于Golang中處理import自定義包出錯(cuò)問(wèn)題的解決辦法,文中通過(guò)圖文介紹的非常詳細(xì),需要的朋友可以參考下
    2023-11-11
  • Golang檢查變量類(lèi)型的四種方式

    Golang檢查變量類(lèi)型的四種方式

    Go提供幾種方法檢查變量的類(lèi)型,在字符串格式化標(biāo)識(shí)%T, 反射方式:reflect.TypeOf, reflect.ValueOf.Kind,另外還有使用類(lèi)型斷言,switch case方式,下面通過(guò)實(shí)例分別介紹這四類(lèi)方法,需要的朋友可以參考下
    2022-10-10
  • VSCode安裝go相關(guān)插件失敗的簡(jiǎn)單解決方案

    VSCode安裝go相關(guān)插件失敗的簡(jiǎn)單解決方案

    這篇文章主要給大家介紹了關(guān)于VSCode安裝go相關(guān)插件失敗的簡(jiǎn)單解決方案,VSCode是我們開(kāi)發(fā)go程序的常用工具,最近安裝的時(shí)候遇到了些問(wèn)題,需要的朋友可以參考下
    2023-07-07
  • Golang信號(hào)量設(shè)計(jì)實(shí)現(xiàn)示例詳解

    Golang信號(hào)量設(shè)計(jì)實(shí)現(xiàn)示例詳解

    這篇文章主要為大家介紹了Golang信號(hào)量設(shè)計(jì)實(shí)現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • Golang服務(wù)中context超時(shí)處理的方法詳解

    Golang服務(wù)中context超時(shí)處理的方法詳解

    在Go語(yǔ)言中,Context是一個(gè)非常重要的概念,它存在于一個(gè)完整的業(yè)務(wù)生命周期內(nèi),Context類(lèi)型是一個(gè)接口類(lèi)型,在實(shí)際應(yīng)用中,我們可以使用Context包來(lái)傳遞請(qǐng)求的元數(shù)據(jù),本文將給大家介紹Golang服務(wù)中context超時(shí)處理的方法和超時(shí)原因,需要的朋友可以參考下
    2023-05-05
  • go 讀取BMP文件頭二進(jìn)制讀取方式

    go 讀取BMP文件頭二進(jìn)制讀取方式

    這篇文章主要介紹了go 讀取BMP文件頭二進(jìn)制讀取方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-12-12
  • Go語(yǔ)言二維數(shù)組的傳參方式

    Go語(yǔ)言二維數(shù)組的傳參方式

    這篇文章主要介紹了Go語(yǔ)言二維數(shù)組的傳參方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-04-04

最新評(píng)論