blob: b727d53c49b369cdb6d329edba3012fb23fce4ec [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 "github.com/mongodb/mongo-go-driver/bson/bsoncodec"
12 "github.com/mongodb/mongo-go-driver/x/bsonx"
13
14 "github.com/mongodb/mongo-go-driver/mongo/options"
15 "github.com/mongodb/mongo-go-driver/x/mongo/driver/session"
16 "github.com/mongodb/mongo-go-driver/x/mongo/driver/topology"
17 "github.com/mongodb/mongo-go-driver/x/mongo/driver/uuid"
18 "github.com/mongodb/mongo-go-driver/x/network/command"
19 "github.com/mongodb/mongo-go-driver/x/network/description"
20 "time"
21)
22
23// CountDocuments handles the full cycle dispatch and execution of a countDocuments command against the provided
24// topology.
25func CountDocuments(
26 ctx context.Context,
27 cmd command.CountDocuments,
28 topo *topology.Topology,
29 selector description.ServerSelector,
30 clientID uuid.UUID,
31 pool *session.Pool,
32 registry *bsoncodec.Registry,
33 opts ...*options.CountOptions,
34) (int64, error) {
35
36 ss, err := topo.SelectServer(ctx, selector)
37 if err != nil {
38 return 0, err
39 }
40
41 desc := ss.Description()
42 conn, err := ss.Connection(ctx)
43 if err != nil {
44 return 0, err
45 }
46 defer conn.Close()
47
48 rp, err := getReadPrefBasedOnTransaction(cmd.ReadPref, cmd.Session)
49 if err != nil {
50 return 0, err
51 }
52 cmd.ReadPref = rp
53
54 // If no explicit session and deployment supports sessions, start implicit session.
55 if cmd.Session == nil && topo.SupportsSessions() {
56 cmd.Session, err = session.NewClientSession(pool, clientID, session.Implicit)
57 if err != nil {
58 return 0, err
59 }
60 defer cmd.Session.EndSession()
61 }
62
63 countOpts := options.MergeCountOptions(opts...)
64
65 // ignore Skip and Limit because we already have these options in the pipeline
66 if countOpts.MaxTime != nil {
67 cmd.Opts = append(cmd.Opts, bsonx.Elem{
68 "maxTimeMS", bsonx.Int64(int64(*countOpts.MaxTime / time.Millisecond)),
69 })
70 }
71 if countOpts.Collation != nil {
72 if desc.WireVersion.Max < 5 {
73 return 0, ErrCollation
74 }
75 cmd.Opts = append(cmd.Opts, bsonx.Elem{"collation", bsonx.Document(countOpts.Collation.ToDocument())})
76 }
77 if countOpts.Hint != nil {
78 hintElem, err := interfaceToElement("hint", countOpts.Hint, registry)
79 if err != nil {
80 return 0, err
81 }
82
83 cmd.Opts = append(cmd.Opts, hintElem)
84 }
85
86 return cmd.RoundTrip(ctx, desc, conn)
87}