blob: 7b7fba4c5bc66b54b6d61259f00904db52e3f6d3 [file] [log] [blame]
Don Newton379ae252019-04-01 12:17:06 -04001// Copyright (C) MongoDB, Inc. 2017-present.
2//
3// Licensed under the Apache License, Version 2.0 (the "License"); you may
4// not use this file except in compliance with the License. You may obtain
5// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
6
7package driver
8
9import (
10 "context"
11 "time"
12
13 "github.com/mongodb/mongo-go-driver/bson/bsoncodec"
14 "github.com/mongodb/mongo-go-driver/x/bsonx"
15
16 "github.com/mongodb/mongo-go-driver/mongo/options"
17 "github.com/mongodb/mongo-go-driver/x/mongo/driver/session"
18 "github.com/mongodb/mongo-go-driver/x/mongo/driver/topology"
19 "github.com/mongodb/mongo-go-driver/x/mongo/driver/uuid"
20 "github.com/mongodb/mongo-go-driver/x/network/command"
21 "github.com/mongodb/mongo-go-driver/x/network/description"
22)
23
24// Count handles the full cycle dispatch and execution of a count command against the provided
25// topology.
26func Count(
27 ctx context.Context,
28 cmd command.Count,
29 topo *topology.Topology,
30 selector description.ServerSelector,
31 clientID uuid.UUID,
32 pool *session.Pool,
33 registry *bsoncodec.Registry,
34 opts ...*options.CountOptions,
35) (int64, error) {
36
37 ss, err := topo.SelectServer(ctx, selector)
38 if err != nil {
39 return 0, err
40 }
41
42 desc := ss.Description()
43 conn, err := ss.Connection(ctx)
44 if err != nil {
45 return 0, err
46 }
47 defer conn.Close()
48
49 rp, err := getReadPrefBasedOnTransaction(cmd.ReadPref, cmd.Session)
50 if err != nil {
51 return 0, err
52 }
53 cmd.ReadPref = rp
54
55 // If no explicit session and deployment supports sessions, start implicit session.
56 if cmd.Session == nil && topo.SupportsSessions() {
57 cmd.Session, err = session.NewClientSession(pool, clientID, session.Implicit)
58 if err != nil {
59 return 0, err
60 }
61 defer cmd.Session.EndSession()
62 }
63
64 countOpts := options.MergeCountOptions(opts...)
65
66 if countOpts.Limit != nil {
67 cmd.Opts = append(cmd.Opts, bsonx.Elem{"limit", bsonx.Int64(*countOpts.Limit)})
68 }
69 if countOpts.MaxTime != nil {
70 cmd.Opts = append(cmd.Opts, bsonx.Elem{
71 "maxTimeMS", bsonx.Int64(int64(*countOpts.MaxTime / time.Millisecond)),
72 })
73 }
74 if countOpts.Skip != nil {
75 cmd.Opts = append(cmd.Opts, bsonx.Elem{"skip", bsonx.Int64(*countOpts.Skip)})
76 }
77 if countOpts.Collation != nil {
78 if desc.WireVersion.Max < 5 {
79 return 0, ErrCollation
80 }
81 cmd.Opts = append(cmd.Opts, bsonx.Elem{"collation", bsonx.Document(countOpts.Collation.ToDocument())})
82 }
83 if countOpts.Hint != nil {
84 hintElem, err := interfaceToElement("hint", countOpts.Hint, registry)
85 if err != nil {
86 return 0, err
87 }
88
89 cmd.Opts = append(cmd.Opts, hintElem)
90 }
91
92 return cmd.RoundTrip(ctx, desc, conn)
93}