// Copyright (C) MongoDB, Inc. 2017-present. // // Licensed under the Apache License, Version 2.0 (the "License"); you may // not use this file except in compliance with the License. You may obtain // a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 package driver import ( "context" "time" "go.mongodb.org/mongo-driver/bson/bsoncodec" "go.mongodb.org/mongo-driver/x/bsonx" "go.mongodb.org/mongo-driver/mongo/options" "go.mongodb.org/mongo-driver/x/mongo/driver/session" "go.mongodb.org/mongo-driver/x/mongo/driver/topology" "go.mongodb.org/mongo-driver/x/mongo/driver/uuid" "go.mongodb.org/mongo-driver/x/network/command" "go.mongodb.org/mongo-driver/x/network/description" ) // Count handles the full cycle dispatch and execution of a count command against the provided // topology. func Count( ctx context.Context, cmd command.Count, topo *topology.Topology, selector description.ServerSelector, clientID uuid.UUID, pool *session.Pool, registry *bsoncodec.Registry, opts ...*options.CountOptions, ) (int64, error) { ss, err := topo.SelectServer(ctx, selector) if err != nil { return 0, err } desc := ss.Description() conn, err := ss.Connection(ctx) if err != nil { return 0, err } defer conn.Close() rp, err := getReadPrefBasedOnTransaction(cmd.ReadPref, cmd.Session) if err != nil { return 0, err } cmd.ReadPref = rp // If no explicit session and deployment supports sessions, start implicit session. if cmd.Session == nil && topo.SupportsSessions() { cmd.Session, err = session.NewClientSession(pool, clientID, session.Implicit) if err != nil { return 0, err } defer cmd.Session.EndSession() } countOpts := options.MergeCountOptions(opts...) if countOpts.Limit != nil { cmd.Opts = append(cmd.Opts, bsonx.Elem{"limit", bsonx.Int64(*countOpts.Limit)}) } if countOpts.MaxTime != nil { cmd.Opts = append(cmd.Opts, bsonx.Elem{ "maxTimeMS", bsonx.Int64(int64(*countOpts.MaxTime / time.Millisecond)), }) } if countOpts.Skip != nil { cmd.Opts = append(cmd.Opts, bsonx.Elem{"skip", bsonx.Int64(*countOpts.Skip)}) } if countOpts.Collation != nil { if desc.WireVersion.Max < 5 { return 0, ErrCollation } collDoc, err := bsonx.ReadDoc(countOpts.Collation.ToDocument()) if err != nil { return 0, err } cmd.Opts = append(cmd.Opts, bsonx.Elem{"collation", bsonx.Document(collDoc)}) } if countOpts.Hint != nil { hintElem, err := interfaceToElement("hint", countOpts.Hint, registry) if err != nil { return 0, err } cmd.Opts = append(cmd.Opts, hintElem) } return cmd.RoundTrip(ctx, desc, conn) }