我的项目中有一个需求,我必须执行一个数据库操作来获取特定类型的用户总数。我所做的是过滤切片中的所有查询,并将Silce传递给我的数据库函数。
这是我调用DB函数的代码段
{
filters = []bson.D{
{{Key: "Mykey", Value: myvalue}},
{{Key: "Mykey", Value: myvalue}},
{{Key: "Mykey", Value: myvalue}},
{{Key: "Mykey", Value: myvalue}},
counts, err := dbmain.NoOfDocumentsInfo(MyDBName, myCollectionName, filters...)
}
下面是我调用的函数
func NoOfDocumentsInfo(DB string, col string, filters ...bson.D) ([]int64, error) {
if nil == dbInstance {
if nil == GetDBInstance() {
logger.Error("Not connecting to DB")
err := errors.New("DB connection error")
return nil, err
}
}
logger.Debugf("%s %s", DB, col)
coll := dbInstance.Database(DB).Collection(col)
counts := make([]int64, len(filters))
for i, filter := range filters {
count, err := coll.CountDocuments(context.TODO(), filter)
if err != nil {
logger.Fatal(err)
return nil, err
}
counts[i] = count
}
return counts, nil
}
正如您所看到的,我多次调用“科尔.CountDocuments”函数。我希望通过将所有筛选器聚合到单个查询中来编写代码,而不多次调用“coll.CountDocuments”函数。
我已尝试使用聚合管道,但“cur”和“result”输出为空。如果运行代码,您将能够看到它。
func NoOfDocumentsInfo(DB string, col string, filters ...bson.D) ([]int64, error) {
if dbInstance == nil {
if GetDBInstance() == nil {
logger.Error("Not connecting to DB")
err := errors.New("DB connection error")
return nil, err
}
}
logger.Debugf("%s %s", DB, col)
coll := dbInstance.Database(DB).Collection(col)
pipeline := make([]bson.M, 0, len(filters)+2)
pipeline = append(pipeline, bson.M{"$match": bson.M{"$or": filters}})
pipeline = append(pipeline, bson.M{"$group": bson.M{"_id": nil, "count": bson.M{"$sum": 1}}})
pipeline = append(pipeline, bson.M{"$group": bson.M{"_id": nil, "count": bson.M{"$first": "$count"}}})
var result struct {
Count int64 `bson:"count"`
}
cur, err := coll.Aggregate(context.TODO(), pipeline)
if err != nil {
logger.Fatal(err)
return nil, err
}
logger.Debugf("cur: %+v", cur)
err = cur.Decode(&result)
logger.Debugf("result: %+v, err: %v", result, err)
if err != nil {
logger.Fatal(err)
return nil, err
}
return []int64{result.Count}, nil
}
1条答案
按热度按时间olmpazwi1#
你必须为
$group
中的每个过滤器添加一个字段,你可以使用$cond
来有条件地递增给定的计数器,但是这很可能最终不使用索引,因此甚至比单独的原始计数查询。另请注意,使用$or
也可能导致跳过索引。另请注意,在$cond
中,您可能必须转换筛选器(例如,将$
添加到字段名称中)。最好为每个过滤器启动并发计数查询(使用
go
),如果它们被索引,它们将快速完成。