golang中Mongodb上的“科尔.CountDocuments”函数的替代方法(聚合管道)

gcuhipw9  于 2023-02-17  发布在  Go
关注(0)|答案(1)|浏览(186)

正如您所看到的,我多次调用“科尔.CountDocuments”函数。我希望通过将所有筛选器聚合到单个查询中来编写代码,而不多次调用“coll.CountDocuments”函数。

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
}

我已尝试使用聚合管道,但“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
}`
u0njafvf

u0njafvf1#

一个简单得多的方法就是我将要在这里分享的方法,让我们从代码开始:

package main

import (
    "context"
    "fmt"
    "time"

    "go.mongodb.org/mongo-driver/bson"
    "go.mongodb.org/mongo-driver/mongo"
    "go.mongodb.org/mongo-driver/mongo/options"
)

var (
    dbInstance *mongo.Client
    ctx        context.Context
    cancel     context.CancelFunc
)

func NoOfDocumentsInfo(client *mongo.Client, DB string, col string, filters bson.A) (int64, error) {
    coll := client.Database(DB).Collection(col)
    myFilters := bson.D{
        bson.E{
            Key:   "$and",
            Value: filters,
        },
    }

    counts, err := coll.CountDocuments(ctx, myFilters)
    if err != nil {
        panic(err)
    }

    return counts, nil
}

func main() {
    ctx, cancel = context.WithTimeout(context.Background(), 20*time.Second)
    defer cancel()

    // set MongoDB connection
    clientOptions := options.Client().ApplyURI("mongodb://root:root@localhost:27017")
    mongoClient, err := mongo.Connect(ctx, clientOptions)
    if err != nil {
        panic(err)
    }
    defer mongoClient.Disconnect(ctx)

    // query with filters
    numDocs, err := NoOfDocumentsInfo(mongoClient, "demodb", "myCollection", bson.A{
        bson.D{bson.E{Key: "Name", Value: bson.D{bson.E{Key: "$eq", Value: "John Doe"}}}},
        bson.D{bson.E{Key: "Song", Value: bson.D{bson.E{Key: "$eq", Value: "White Roses"}}}},
    })
    if err != nil {
        panic(err)
    }
    fmt.Println("num docs:", numDocs)
}

让我们看看应用于代码的相关更改:

  • 期望一个名为filters的参数,其类型为bson.A,这是MongoDB环境中array的类型。
  • 以如下方式构建bson.D(切片)类型的myFilters变量,其中包含以下单个项目(bson.E):
  • Key是逻辑运算符
  • Value是传入函数的数组
  • 构建数组以传递给具有所有所需过滤器的函数(例如,两个相等条件:一个在X1 M8 N1 X密钥上,另一个在X1 M9 N1 X上)。

最后,我还对如何打开MongoDB连接以及如何释放分配的资源做了一些改进。
如果这解决了你的问题,请告诉我,谢谢!

相关问题