Golang對(duì)mongodb進(jìn)行聚合查詢?cè)斀?/h1>
更新時(shí)間:2023年02月10日 10:51:38 作者:金色旭光
這篇文章主要為大家詳細(xì)介紹了Golang對(duì)mongodb進(jìn)行聚合查詢的方法,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Golang有一點(diǎn)的幫助,需要的可以參考一下
mongodb的環(huán)境搭建參考前面一篇通過(guò)mongo-driver使用說(shuō)明 GO 包管理機(jī)制
1.BSON介紹
在Go中使用BSON對(duì)象構(gòu)建操作命令
在我們發(fā)送查詢給數(shù)據(jù)庫(kù)之前, 很重要的一點(diǎn)是,理解Go Driver是如何和BSON對(duì)象協(xié)同工作的。
JSON文檔在MongoDB里面以二進(jìn)制形式存儲(chǔ), 被稱作BSON(二進(jìn)制編碼的JSON)。不像其他的數(shù)據(jù)庫(kù)保存JSON數(shù)據(jù)為簡(jiǎn)單的字符串和數(shù)字, BSON擴(kuò)展了JSON的保存形式, 包括額外的類型, 比如int, long, date, floating point以及decimal128。這使得它讓應(yīng)用程序更容易來(lái)可靠地處理、排序和比較數(shù)據(jù)。
Go Driver有兩個(gè)系列的類型表示BSON數(shù)據(jù):D系列類型和Raw系列類型。
D系列的類型使用原生的Go類型簡(jiǎn)單地構(gòu)建BSON對(duì)象。這可以非常有用的來(lái)創(chuàng)建傳遞給MongoDB的命令。 D系列包含4種類型:
- – D:一個(gè)BSON文檔。這個(gè)類型應(yīng)該被用在順序很重要的場(chǎng)景, 比如MongoDB命令。
- – M: 一個(gè)無(wú)需map。 它和D是一樣的, 除了它不保留順序。
- – A: 一個(gè)BSON數(shù)組。
- – E: 在D里面的一個(gè)單一的子項(xiàng)。
這里有一個(gè)使用D類型構(gòu)建的過(guò)濾文檔的例子, 它可能被用在查詢name字段匹配“Alice”或者“Bob”的文檔:
bson.D{{
"name",
bson.D{{
"$in",
bson.A{"Alice", "Bob"}
}}
}}
2.過(guò)濾查詢
2.1go查詢
package main
import (
"context"
"fmt"
"log"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"go.mongodb.org/mongo-driver/bson"
)
type Student struct {
Name string
Score int
}
func main() {
// 設(shè)置客戶端連接配置
clientOptions := options.Client().ApplyURI("mongodb://admin:123456@localhost:27017")
// 連接到MongoDB
client, err := mongo.Connect(context.TODO(), clientOptions)
if err != nil {
log.Fatal(err)
}
// 檢查連接
err = client.Ping(context.TODO(), nil)
if err != nil {
log.Fatal(err)
}
fmt.Println("Connected to MongoDB!")
collection := client.Database("demo").Collection("student")
s1 := Student{"小紅", 66}
s2 := Student{"小蘭", 70}
s3 := Student{"小黃", 86}
s4 := Student{"小張", 92}
students := []interface{}{s1, s2, s3, s4}
res, err := collection.InsertMany(context.TODO(), students)
if err != nil {
log.Fatal(err)
}
fmt.Println("插入數(shù)據(jù)完成", res.InsertedIDs)
aggreData := []map[string]interface{}{}
scoreArray := [5]int{60, 70, 80, 90, 100}
for i := 0; i<len(scoreArray)-1; i++{
filter := bson.M{
"score": bson.M{
"$gt": scoreArray[i],
"$lt": scoreArray[i+1],
},
}
count, err := collection.CountDocuments(context.TODO(), filter)
if err != nil {
log.Printf("get metric error %s", err)
}
if count > 0 {
temp := map[string]interface{}{}
temp["count"] = count
aggreData = append(aggreData, temp)
}
}
fmt.Println("get finish!")
for _, value := range aggreData {
fmt.Println(value)
}
}
admin> use demo
switched to db demo
demo> show tables
student
demo> db.student.find()
[
{ _id: ObjectId("63e25fa9c6fe361e9f5e7e6e"), name: '小紅', score: 66 },
{ _id: ObjectId("63e25fa9c6fe361e9f5e7e6f"), name: '小蘭', score: 70 },
{ _id: ObjectId("63e25fa9c6fe361e9f5e7e70"), name: '小黃', score: 86 },
{ _id: ObjectId("63e25fa9c6fe361e9f5e7e71"), name: '小張', score: 92 }
]
? mongo go run hello.go
Connected to MongoDB!
插入數(shù)據(jù)完成 [ObjectID("63e26329b1f99ae321f895c2") ObjectID("63e26329b1f99ae321f895c3") ObjectID("63e26329b1f99ae321f895c4") ObjectID("63e26329b1f99ae321f895c5")]
get finish!
map[count:1]
map[count:1]
map[count:1]
2.2bucket命令
以上的命令其實(shí)是用來(lái)替換bucket命令。bucket命令是3.4的新功能,功能是可以對(duì)傳入的一組查詢數(shù)據(jù)分組查詢并統(tǒng)計(jì)。如傳入查詢數(shù)據(jù)為[0, 10, 20, 30],可以查詢出0~10的數(shù)據(jù),10~20的數(shù)據(jù)。
cond := make([]bson.M, 0)
cond = append(cond, bson.M{"$match": bson.M{"user_id": userID}})
cond = append(cond, bson.M{
"$bucket": bson.D{
bson.E{Key: "groupBy", Value: "$" + queryField},
bson.E{Key: "default", Value: "_others_"},
bson.E{Key: "boundaries", Value: boundries},
bson.E{Key: "output", Value: bson.D{bson.E{Key: "count", Value: bson.M{"$sum": 1}}}},
}})
aggreData := s.aggregateMongoQuery(collection, cond)
3.聚合查詢
3.1mongo命令使用
使用mongodb肯定離不開聚合查詢這種威力強(qiáng)大的操作。下面實(shí)現(xiàn)一個(gè)提取數(shù)組中元素,重命名,匹配區(qū)間,統(tǒng)計(jì)總數(shù)這樣一個(gè)操作,使用到的命令包括:
- unwind:將數(shù)組中的每一個(gè)值拆分為單獨(dú)的文檔
- project:提取文檔中元素或重命名
- match:匹配文檔中元素
- group:統(tǒng)計(jì)文檔
插入數(shù)據(jù)
demo> db.student.insert({"field": "score", "num": [12, 23, 34, 45, 56, 67, 78, 89]})
{
acknowledged: true,
insertedIds: { '0': ObjectId("63e3b26b029e307c2c8c46e6") }
}
mongo命令查詢
demo> db.student.aggregate([{ $unwind:"$num"}, {$project:{value: "$num"}}, {$match: {value:{$gte: 40, $lt: 90}}}, {$group: {_id: "in_40_90", count: {$sum: 1}}}])
[ { _id: 'in_40_90', count: 5 } ]
程序就是將以上命令翻譯成go語(yǔ)言執(zhí)行
3.2go 聚合查詢
package main
import (
"context"
"fmt"
"log"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"go.mongodb.org/mongo-driver/bson"
)
type Student struct {
Name string
Score int
}
func main() {
// 設(shè)置客戶端連接配置
clientOptions := options.Client().ApplyURI("mongodb://admin:123456@localhost:27017")
// 連接到MongoDB
client, err := mongo.Connect(context.TODO(), clientOptions)
if err != nil {
log.Fatal(err)
}
// 檢查連接
err = client.Ping(context.TODO(), nil)
if err != nil {
log.Fatal(err)
}
fmt.Println("Connected to MongoDB!")
collection := client.Database("demo").Collection("student")
unwind := bson.D{{"$unwind", "$num"}}
project := bson.D{{
"$project", bson.D{{
"value", "$num",
}},
}}
match := bson.D{{
"$match", bson.D{{
"value", bson.D{{"$gte", 40}, {"$lt", 90}},
}},
}}
group := bson.D{{
"$group", bson.D{
{"_id", nil},
{"count", bson.D{{"$sum", 1}}},
},
}}
showInfoCursor, err := collection.Aggregate(context.TODO(), mongo.Pipeline{unwind, project, match, group})
var showsWithInfo []map[string]interface{}
if err = showInfoCursor.All(context.TODO(), &showsWithInfo); err != nil {
log.Printf("collection %s", err)
panic(err)
}
for _, value := range showsWithInfo {
fmt.Println(value)
}
}
? mongo go run hello.go
Connected to MongoDB!
map[_id:<nil> count:5]
可以看到結(jié)果和mongo命令是一樣的
以上就是Golang對(duì)mongodb進(jìn)行聚合查詢?cè)斀獾脑敿?xì)內(nèi)容,更多關(guān)于Golang mongodb聚合查詢的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
-
go語(yǔ)言中Timer和Ticker兩種計(jì)時(shí)器的使用
go語(yǔ)言中有Timer和Ticker這樣的兩種計(jì)時(shí)器,兩種計(jì)時(shí)器分別實(shí)現(xiàn)了不同的計(jì)時(shí)功能,本文主要介紹了go語(yǔ)言中Timer和Ticker兩種計(jì)時(shí)器的使用,感興趣的可以了解一下 2024-08-08
-
go?sync.Once實(shí)現(xiàn)高效單例模式詳解
這篇文章主要為大家介紹了go?sync.Once實(shí)現(xiàn)高效單例模式詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪 2023-03-03
-
Go語(yǔ)言學(xué)習(xí)之結(jié)構(gòu)體和方法使用詳解
這篇文章主要為大家詳細(xì)介紹了Go語(yǔ)言中結(jié)構(gòu)體和方法的使用,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Go語(yǔ)言有一定的幫助,需要的可以參考一下 2022-04-04
-
深入解析Go語(yǔ)言中crypto/subtle加密庫(kù)
本文主要介紹了深入解析Go語(yǔ)言中crypto/subtle加密庫(kù),詳細(xì)介紹crypto/subtle加密庫(kù)主要函數(shù)的用途、工作原理及實(shí)際應(yīng)用,具有一定的參考價(jià)值,感興趣的可以了解一下 2024-02-02
最新評(píng)論
mongodb的環(huán)境搭建參考前面一篇通過(guò)mongo-driver使用說(shuō)明 GO 包管理機(jī)制
1.BSON介紹
在Go中使用BSON對(duì)象構(gòu)建操作命令
在我們發(fā)送查詢給數(shù)據(jù)庫(kù)之前, 很重要的一點(diǎn)是,理解Go Driver是如何和BSON對(duì)象協(xié)同工作的。
JSON文檔在MongoDB里面以二進(jìn)制形式存儲(chǔ), 被稱作BSON(二進(jìn)制編碼的JSON)。不像其他的數(shù)據(jù)庫(kù)保存JSON數(shù)據(jù)為簡(jiǎn)單的字符串和數(shù)字, BSON擴(kuò)展了JSON的保存形式, 包括額外的類型, 比如int, long, date, floating point以及decimal128。這使得它讓應(yīng)用程序更容易來(lái)可靠地處理、排序和比較數(shù)據(jù)。
Go Driver有兩個(gè)系列的類型表示BSON數(shù)據(jù):D系列類型和Raw系列類型。
D系列的類型使用原生的Go類型簡(jiǎn)單地構(gòu)建BSON對(duì)象。這可以非常有用的來(lái)創(chuàng)建傳遞給MongoDB的命令。 D系列包含4種類型:
- – D:一個(gè)BSON文檔。這個(gè)類型應(yīng)該被用在順序很重要的場(chǎng)景, 比如MongoDB命令。
- – M: 一個(gè)無(wú)需map。 它和D是一樣的, 除了它不保留順序。
- – A: 一個(gè)BSON數(shù)組。
- – E: 在D里面的一個(gè)單一的子項(xiàng)。
這里有一個(gè)使用D類型構(gòu)建的過(guò)濾文檔的例子, 它可能被用在查詢name字段匹配“Alice”或者“Bob”的文檔:
bson.D{{ "name", bson.D{{ "$in", bson.A{"Alice", "Bob"} }} }}
2.過(guò)濾查詢
2.1go查詢
package main import ( "context" "fmt" "log" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" "go.mongodb.org/mongo-driver/bson" ) type Student struct { Name string Score int } func main() { // 設(shè)置客戶端連接配置 clientOptions := options.Client().ApplyURI("mongodb://admin:123456@localhost:27017") // 連接到MongoDB client, err := mongo.Connect(context.TODO(), clientOptions) if err != nil { log.Fatal(err) } // 檢查連接 err = client.Ping(context.TODO(), nil) if err != nil { log.Fatal(err) } fmt.Println("Connected to MongoDB!") collection := client.Database("demo").Collection("student") s1 := Student{"小紅", 66} s2 := Student{"小蘭", 70} s3 := Student{"小黃", 86} s4 := Student{"小張", 92} students := []interface{}{s1, s2, s3, s4} res, err := collection.InsertMany(context.TODO(), students) if err != nil { log.Fatal(err) } fmt.Println("插入數(shù)據(jù)完成", res.InsertedIDs) aggreData := []map[string]interface{}{} scoreArray := [5]int{60, 70, 80, 90, 100} for i := 0; i<len(scoreArray)-1; i++{ filter := bson.M{ "score": bson.M{ "$gt": scoreArray[i], "$lt": scoreArray[i+1], }, } count, err := collection.CountDocuments(context.TODO(), filter) if err != nil { log.Printf("get metric error %s", err) } if count > 0 { temp := map[string]interface{}{} temp["count"] = count aggreData = append(aggreData, temp) } } fmt.Println("get finish!") for _, value := range aggreData { fmt.Println(value) } }
admin> use demo switched to db demo demo> show tables student demo> db.student.find() [ { _id: ObjectId("63e25fa9c6fe361e9f5e7e6e"), name: '小紅', score: 66 }, { _id: ObjectId("63e25fa9c6fe361e9f5e7e6f"), name: '小蘭', score: 70 }, { _id: ObjectId("63e25fa9c6fe361e9f5e7e70"), name: '小黃', score: 86 }, { _id: ObjectId("63e25fa9c6fe361e9f5e7e71"), name: '小張', score: 92 } ]
? mongo go run hello.go
Connected to MongoDB!
插入數(shù)據(jù)完成 [ObjectID("63e26329b1f99ae321f895c2") ObjectID("63e26329b1f99ae321f895c3") ObjectID("63e26329b1f99ae321f895c4") ObjectID("63e26329b1f99ae321f895c5")]
get finish!
map[count:1]
map[count:1]
map[count:1]
2.2bucket命令
以上的命令其實(shí)是用來(lái)替換bucket命令。bucket命令是3.4的新功能,功能是可以對(duì)傳入的一組查詢數(shù)據(jù)分組查詢并統(tǒng)計(jì)。如傳入查詢數(shù)據(jù)為[0, 10, 20, 30],可以查詢出0~10的數(shù)據(jù),10~20的數(shù)據(jù)。
cond := make([]bson.M, 0)
cond = append(cond, bson.M{"$match": bson.M{"user_id": userID}})
cond = append(cond, bson.M{
"$bucket": bson.D{
bson.E{Key: "groupBy", Value: "$" + queryField},
bson.E{Key: "default", Value: "_others_"},
bson.E{Key: "boundaries", Value: boundries},
bson.E{Key: "output", Value: bson.D{bson.E{Key: "count", Value: bson.M{"$sum": 1}}}},
}})
aggreData := s.aggregateMongoQuery(collection, cond)
3.聚合查詢
3.1mongo命令使用
使用mongodb肯定離不開聚合查詢這種威力強(qiáng)大的操作。下面實(shí)現(xiàn)一個(gè)提取數(shù)組中元素,重命名,匹配區(qū)間,統(tǒng)計(jì)總數(shù)這樣一個(gè)操作,使用到的命令包括:
- unwind:將數(shù)組中的每一個(gè)值拆分為單獨(dú)的文檔
- project:提取文檔中元素或重命名
- match:匹配文檔中元素
- group:統(tǒng)計(jì)文檔
插入數(shù)據(jù)
demo> db.student.insert({"field": "score", "num": [12, 23, 34, 45, 56, 67, 78, 89]}) { acknowledged: true, insertedIds: { '0': ObjectId("63e3b26b029e307c2c8c46e6") } }
mongo命令查詢
demo> db.student.aggregate([{ $unwind:"$num"}, {$project:{value: "$num"}}, {$match: {value:{$gte: 40, $lt: 90}}}, {$group: {_id: "in_40_90", count: {$sum: 1}}}]) [ { _id: 'in_40_90', count: 5 } ]
程序就是將以上命令翻譯成go語(yǔ)言執(zhí)行
3.2go 聚合查詢
package main import ( "context" "fmt" "log" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" "go.mongodb.org/mongo-driver/bson" ) type Student struct { Name string Score int } func main() { // 設(shè)置客戶端連接配置 clientOptions := options.Client().ApplyURI("mongodb://admin:123456@localhost:27017") // 連接到MongoDB client, err := mongo.Connect(context.TODO(), clientOptions) if err != nil { log.Fatal(err) } // 檢查連接 err = client.Ping(context.TODO(), nil) if err != nil { log.Fatal(err) } fmt.Println("Connected to MongoDB!") collection := client.Database("demo").Collection("student") unwind := bson.D{{"$unwind", "$num"}} project := bson.D{{ "$project", bson.D{{ "value", "$num", }}, }} match := bson.D{{ "$match", bson.D{{ "value", bson.D{{"$gte", 40}, {"$lt", 90}}, }}, }} group := bson.D{{ "$group", bson.D{ {"_id", nil}, {"count", bson.D{{"$sum", 1}}}, }, }} showInfoCursor, err := collection.Aggregate(context.TODO(), mongo.Pipeline{unwind, project, match, group}) var showsWithInfo []map[string]interface{} if err = showInfoCursor.All(context.TODO(), &showsWithInfo); err != nil { log.Printf("collection %s", err) panic(err) } for _, value := range showsWithInfo { fmt.Println(value) } }
? mongo go run hello.go
Connected to MongoDB!
map[_id:<nil> count:5]
可以看到結(jié)果和mongo命令是一樣的
以上就是Golang對(duì)mongodb進(jìn)行聚合查詢?cè)斀獾脑敿?xì)內(nèi)容,更多關(guān)于Golang mongodb聚合查詢的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
go語(yǔ)言中Timer和Ticker兩種計(jì)時(shí)器的使用
go語(yǔ)言中有Timer和Ticker這樣的兩種計(jì)時(shí)器,兩種計(jì)時(shí)器分別實(shí)現(xiàn)了不同的計(jì)時(shí)功能,本文主要介紹了go語(yǔ)言中Timer和Ticker兩種計(jì)時(shí)器的使用,感興趣的可以了解一下2024-08-08go?sync.Once實(shí)現(xiàn)高效單例模式詳解
這篇文章主要為大家介紹了go?sync.Once實(shí)現(xiàn)高效單例模式詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03Go語(yǔ)言學(xué)習(xí)之結(jié)構(gòu)體和方法使用詳解
這篇文章主要為大家詳細(xì)介紹了Go語(yǔ)言中結(jié)構(gòu)體和方法的使用,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Go語(yǔ)言有一定的幫助,需要的可以參考一下2022-04-04深入解析Go語(yǔ)言中crypto/subtle加密庫(kù)
本文主要介紹了深入解析Go語(yǔ)言中crypto/subtle加密庫(kù),詳細(xì)介紹crypto/subtle加密庫(kù)主要函數(shù)的用途、工作原理及實(shí)際應(yīng)用,具有一定的參考價(jià)值,感興趣的可以了解一下2024-02-02