mongodb - Go mongodb驱动程序忽略聚合中的管道
问题描述
根据https://github.com/simagix/mongo-go-examples/blob/master/examples/aggregate_array_test.go上的示例,我创建了以下代码,该代码在集合上运行管道:
pipeline := `[
{
$group: {
_id: {
year: { $year: "$action_date" },
month: { $month: "$action_date" },
day: { $dayOfMonth: "$action_date" },
},
count: { $sum: 1 }
}
}
]`
var doc bson.M
var cur *mongo.Cursor
collection := apiContext.MongoClient.Database(apiContext.DatabaseName).Collection(util.ActionCollection)
opts := options.Aggregate()
if cur, err = collection.Aggregate(ctx, MongoPipeline(pipeline), opts); err != nil {
}
defer cur.Close(ctx)
for cur.Next(ctx) {
cur.Decode(&doc)
fmt.Println(doc["count"])
}
我没有收到任何错误,但输出不是我所期望的。我没有返回基于日期的文档计数,而是获取集合中的所有文档。
我不知道我错过了什么,但我不应该得到分组结果吗?
解决方案
我不知道我错过了什么,但我不应该得到分组结果吗?
这里有几件事需要指出。该代码示例使用MongoPipelinegithub.com/simagix/keyhole/mdb
的模块。此函数应该采用您的字符串格式的 MongoDB 管道并转换为bson。这是mongo-go-driver用来发送到 MongoDB 服务器的格式。$group
不幸的是,该MongoPipeline
函数没有返回error
您的代码可以捕获的任何内容,但该函数正在使用encoding/json
模块将管道转换为bson
,并且存在错误。您得到的 JSON 解析错误是:
invalid character '$' looking for beginning of object key string
=> 因为键需要用"
invalid character '}' looking for beginning of object key string
=> 因为 . 后面有多余的逗号}
。
由于这些错误,MongoPipeline
返回空数组[]
,这意味着未定义的聚合管道,并将返回集合中的所有文档。
正确的管道 JSON 字符串是(可以使用jsonlint.com来验证)
[{
"$group": {
"_id": {
"year": {
"$year": "$action_date"
},
"month": {
"$month": "$action_date"
},
"day": {
"$dayOfMonth": "$action_date"
}
},
"count": {
"$sum": 1
}
}
}]
根据您的用例,您可以跳过keyhole/mdb
和encoding/json
模块,bson
直接使用。例如:
groupStage := `{
"$group": {
"_id": {
"year": { "$year": "$action_date" },
"month": { "$month": "$action_date" },
"day": { "$dayOfMonth": "$action_date" }
},
"count": { "$sum": 1 }
}
}`
var group bson.M
err = bson.UnmarshalExtJSON([]byte(groupStage), false, &group)
if err!=nil {
fmt.Println(err)
}
var doc bson.M
// You can add another stage i.e. bson.A{group, sort, project}
cursor, err := collection.Aggregate(context.Background(), bson.A{group})
defer cursor.Close(context.Background())
if err!=nil {
log.Fatal(err)
}
或者,您也可以直接将mongo.Pipeline与bson.M或bson.D一起使用:
pipeline := mongo.Pipeline{
{{"$group", bson.D{
{"_id", bson.D{
{"year", bson.D{{"$year", "$action_date"}}},
{"month", bson.D{{"$month", "$action_date"}}},
{"day", bson.D{{"$dayOfMonth", "$action_date"}}}
}},
{"count", bson.D{{"$sum", 1}}},
}}},
}
上面的示例是使用当前稳定的MongoDB Go 驱动程序v1.1.3 编写的。
推荐阅读
- c# - 如何使用多个模式和特定表搭建脚手架?
- c++ - 有没有办法使用win32在窗口的标题栏中绘制彩色矩形
- python - 为什么我的代码在抓取时陷入无限循环?
- ada - 如何在 Spark_Ada 中检查 Storage_Error
- python - Python中的“%%”是什么意思
- javascript - 使用 react admin 设置 redux 提供程序
- mongoose - Mongoose .save() 不能在对象中保存数字
- r - 零截断泊松分布:错误代码 100
- java - Java Swing在图标内对齐文本
- firebase - 准备 Firestore 成员的年龄明智报告