github.com/mdaxf/iac@v0.0.0-20240519030858-58a061660378/vendor_skip/go.mongodb.org/mongo-driver/x/mongo/driver/operation/aggregate.go (about)

     1  // Copyright (C) MongoDB, Inc. 2019-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  
     7  package operation
     8  
     9  import (
    10  	"context"
    11  	"errors"
    12  	"time"
    13  
    14  	"go.mongodb.org/mongo-driver/bson/bsontype"
    15  	"go.mongodb.org/mongo-driver/event"
    16  	"go.mongodb.org/mongo-driver/mongo/description"
    17  	"go.mongodb.org/mongo-driver/mongo/readconcern"
    18  	"go.mongodb.org/mongo-driver/mongo/readpref"
    19  	"go.mongodb.org/mongo-driver/mongo/writeconcern"
    20  	"go.mongodb.org/mongo-driver/x/bsonx/bsoncore"
    21  	"go.mongodb.org/mongo-driver/x/mongo/driver"
    22  	"go.mongodb.org/mongo-driver/x/mongo/driver/session"
    23  )
    24  
    25  // Aggregate represents an aggregate operation.
    26  type Aggregate struct {
    27  	allowDiskUse             *bool
    28  	batchSize                *int32
    29  	bypassDocumentValidation *bool
    30  	collation                bsoncore.Document
    31  	comment                  *string
    32  	hint                     bsoncore.Value
    33  	maxTime                  *time.Duration
    34  	pipeline                 bsoncore.Document
    35  	session                  *session.Client
    36  	clock                    *session.ClusterClock
    37  	collection               string
    38  	monitor                  *event.CommandMonitor
    39  	database                 string
    40  	deployment               driver.Deployment
    41  	readConcern              *readconcern.ReadConcern
    42  	readPreference           *readpref.ReadPref
    43  	retry                    *driver.RetryMode
    44  	selector                 description.ServerSelector
    45  	writeConcern             *writeconcern.WriteConcern
    46  	crypt                    driver.Crypt
    47  	serverAPI                *driver.ServerAPIOptions
    48  	let                      bsoncore.Document
    49  	hasOutputStage           bool
    50  	customOptions            map[string]bsoncore.Value
    51  	timeout                  *time.Duration
    52  
    53  	result driver.CursorResponse
    54  }
    55  
    56  // NewAggregate constructs and returns a new Aggregate.
    57  func NewAggregate(pipeline bsoncore.Document) *Aggregate {
    58  	return &Aggregate{
    59  		pipeline: pipeline,
    60  	}
    61  }
    62  
    63  // Result returns the result of executing this operation.
    64  func (a *Aggregate) Result(opts driver.CursorOptions) (*driver.BatchCursor, error) {
    65  
    66  	clientSession := a.session
    67  
    68  	clock := a.clock
    69  	opts.ServerAPI = a.serverAPI
    70  	return driver.NewBatchCursor(a.result, clientSession, clock, opts)
    71  }
    72  
    73  // ResultCursorResponse returns the underlying CursorResponse result of executing this
    74  // operation.
    75  func (a *Aggregate) ResultCursorResponse() driver.CursorResponse {
    76  	return a.result
    77  }
    78  
    79  func (a *Aggregate) processResponse(info driver.ResponseInfo) error {
    80  	var err error
    81  
    82  	a.result, err = driver.NewCursorResponse(info)
    83  	return err
    84  
    85  }
    86  
    87  // Execute runs this operations and returns an error if the operation did not execute successfully.
    88  func (a *Aggregate) Execute(ctx context.Context) error {
    89  	if a.deployment == nil {
    90  		return errors.New("the Aggregate operation must have a Deployment set before Execute can be called")
    91  	}
    92  
    93  	return driver.Operation{
    94  		CommandFn:         a.command,
    95  		ProcessResponseFn: a.processResponse,
    96  
    97  		Client:                         a.session,
    98  		Clock:                          a.clock,
    99  		CommandMonitor:                 a.monitor,
   100  		Database:                       a.database,
   101  		Deployment:                     a.deployment,
   102  		ReadConcern:                    a.readConcern,
   103  		ReadPreference:                 a.readPreference,
   104  		Type:                           driver.Read,
   105  		RetryMode:                      a.retry,
   106  		Selector:                       a.selector,
   107  		WriteConcern:                   a.writeConcern,
   108  		Crypt:                          a.crypt,
   109  		MinimumWriteConcernWireVersion: 5,
   110  		ServerAPI:                      a.serverAPI,
   111  		IsOutputAggregate:              a.hasOutputStage,
   112  		MaxTime:                        a.maxTime,
   113  		Timeout:                        a.timeout,
   114  	}.Execute(ctx)
   115  
   116  }
   117  
   118  func (a *Aggregate) command(dst []byte, desc description.SelectedServer) ([]byte, error) {
   119  	header := bsoncore.Value{Type: bsontype.String, Data: bsoncore.AppendString(nil, a.collection)}
   120  	if a.collection == "" {
   121  		header = bsoncore.Value{Type: bsontype.Int32, Data: []byte{0x01, 0x00, 0x00, 0x00}}
   122  	}
   123  	dst = bsoncore.AppendValueElement(dst, "aggregate", header)
   124  
   125  	cursorIdx, cursorDoc := bsoncore.AppendDocumentStart(nil)
   126  	if a.allowDiskUse != nil {
   127  
   128  		dst = bsoncore.AppendBooleanElement(dst, "allowDiskUse", *a.allowDiskUse)
   129  	}
   130  	if a.batchSize != nil {
   131  		cursorDoc = bsoncore.AppendInt32Element(cursorDoc, "batchSize", *a.batchSize)
   132  	}
   133  	if a.bypassDocumentValidation != nil {
   134  
   135  		dst = bsoncore.AppendBooleanElement(dst, "bypassDocumentValidation", *a.bypassDocumentValidation)
   136  	}
   137  	if a.collation != nil {
   138  
   139  		if desc.WireVersion == nil || !desc.WireVersion.Includes(5) {
   140  			return nil, errors.New("the 'collation' command parameter requires a minimum server wire version of 5")
   141  		}
   142  		dst = bsoncore.AppendDocumentElement(dst, "collation", a.collation)
   143  	}
   144  	if a.comment != nil {
   145  
   146  		dst = bsoncore.AppendStringElement(dst, "comment", *a.comment)
   147  	}
   148  	if a.hint.Type != bsontype.Type(0) {
   149  
   150  		dst = bsoncore.AppendValueElement(dst, "hint", a.hint)
   151  	}
   152  	if a.pipeline != nil {
   153  
   154  		dst = bsoncore.AppendArrayElement(dst, "pipeline", a.pipeline)
   155  	}
   156  	if a.let != nil {
   157  		dst = bsoncore.AppendDocumentElement(dst, "let", a.let)
   158  	}
   159  	for optionName, optionValue := range a.customOptions {
   160  		dst = bsoncore.AppendValueElement(dst, optionName, optionValue)
   161  	}
   162  	cursorDoc, _ = bsoncore.AppendDocumentEnd(cursorDoc, cursorIdx)
   163  	dst = bsoncore.AppendDocumentElement(dst, "cursor", cursorDoc)
   164  
   165  	return dst, nil
   166  }
   167  
   168  // AllowDiskUse enables writing to temporary files. When true, aggregation stages can write to the dbPath/_tmp directory.
   169  func (a *Aggregate) AllowDiskUse(allowDiskUse bool) *Aggregate {
   170  	if a == nil {
   171  		a = new(Aggregate)
   172  	}
   173  
   174  	a.allowDiskUse = &allowDiskUse
   175  	return a
   176  }
   177  
   178  // BatchSize specifies the number of documents to return in every batch.
   179  func (a *Aggregate) BatchSize(batchSize int32) *Aggregate {
   180  	if a == nil {
   181  		a = new(Aggregate)
   182  	}
   183  
   184  	a.batchSize = &batchSize
   185  	return a
   186  }
   187  
   188  // BypassDocumentValidation allows the write to opt-out of document level validation. This only applies when the $out stage is specified.
   189  func (a *Aggregate) BypassDocumentValidation(bypassDocumentValidation bool) *Aggregate {
   190  	if a == nil {
   191  		a = new(Aggregate)
   192  	}
   193  
   194  	a.bypassDocumentValidation = &bypassDocumentValidation
   195  	return a
   196  }
   197  
   198  // Collation specifies a collation. This option is only valid for server versions 3.4 and above.
   199  func (a *Aggregate) Collation(collation bsoncore.Document) *Aggregate {
   200  	if a == nil {
   201  		a = new(Aggregate)
   202  	}
   203  
   204  	a.collation = collation
   205  	return a
   206  }
   207  
   208  // Comment specifies an arbitrary string to help trace the operation through the database profiler, currentOp, and logs.
   209  func (a *Aggregate) Comment(comment string) *Aggregate {
   210  	if a == nil {
   211  		a = new(Aggregate)
   212  	}
   213  
   214  	a.comment = &comment
   215  	return a
   216  }
   217  
   218  // Hint specifies the index to use.
   219  func (a *Aggregate) Hint(hint bsoncore.Value) *Aggregate {
   220  	if a == nil {
   221  		a = new(Aggregate)
   222  	}
   223  
   224  	a.hint = hint
   225  	return a
   226  }
   227  
   228  // MaxTime specifies the maximum amount of time to allow the query to run on the server.
   229  func (a *Aggregate) MaxTime(maxTime *time.Duration) *Aggregate {
   230  	if a == nil {
   231  		a = new(Aggregate)
   232  	}
   233  
   234  	a.maxTime = maxTime
   235  	return a
   236  }
   237  
   238  // Pipeline determines how data is transformed for an aggregation.
   239  func (a *Aggregate) Pipeline(pipeline bsoncore.Document) *Aggregate {
   240  	if a == nil {
   241  		a = new(Aggregate)
   242  	}
   243  
   244  	a.pipeline = pipeline
   245  	return a
   246  }
   247  
   248  // Session sets the session for this operation.
   249  func (a *Aggregate) Session(session *session.Client) *Aggregate {
   250  	if a == nil {
   251  		a = new(Aggregate)
   252  	}
   253  
   254  	a.session = session
   255  	return a
   256  }
   257  
   258  // ClusterClock sets the cluster clock for this operation.
   259  func (a *Aggregate) ClusterClock(clock *session.ClusterClock) *Aggregate {
   260  	if a == nil {
   261  		a = new(Aggregate)
   262  	}
   263  
   264  	a.clock = clock
   265  	return a
   266  }
   267  
   268  // Collection sets the collection that this command will run against.
   269  func (a *Aggregate) Collection(collection string) *Aggregate {
   270  	if a == nil {
   271  		a = new(Aggregate)
   272  	}
   273  
   274  	a.collection = collection
   275  	return a
   276  }
   277  
   278  // CommandMonitor sets the monitor to use for APM events.
   279  func (a *Aggregate) CommandMonitor(monitor *event.CommandMonitor) *Aggregate {
   280  	if a == nil {
   281  		a = new(Aggregate)
   282  	}
   283  
   284  	a.monitor = monitor
   285  	return a
   286  }
   287  
   288  // Database sets the database to run this operation against.
   289  func (a *Aggregate) Database(database string) *Aggregate {
   290  	if a == nil {
   291  		a = new(Aggregate)
   292  	}
   293  
   294  	a.database = database
   295  	return a
   296  }
   297  
   298  // Deployment sets the deployment to use for this operation.
   299  func (a *Aggregate) Deployment(deployment driver.Deployment) *Aggregate {
   300  	if a == nil {
   301  		a = new(Aggregate)
   302  	}
   303  
   304  	a.deployment = deployment
   305  	return a
   306  }
   307  
   308  // ReadConcern specifies the read concern for this operation.
   309  func (a *Aggregate) ReadConcern(readConcern *readconcern.ReadConcern) *Aggregate {
   310  	if a == nil {
   311  		a = new(Aggregate)
   312  	}
   313  
   314  	a.readConcern = readConcern
   315  	return a
   316  }
   317  
   318  // ReadPreference set the read preference used with this operation.
   319  func (a *Aggregate) ReadPreference(readPreference *readpref.ReadPref) *Aggregate {
   320  	if a == nil {
   321  		a = new(Aggregate)
   322  	}
   323  
   324  	a.readPreference = readPreference
   325  	return a
   326  }
   327  
   328  // ServerSelector sets the selector used to retrieve a server.
   329  func (a *Aggregate) ServerSelector(selector description.ServerSelector) *Aggregate {
   330  	if a == nil {
   331  		a = new(Aggregate)
   332  	}
   333  
   334  	a.selector = selector
   335  	return a
   336  }
   337  
   338  // WriteConcern sets the write concern for this operation.
   339  func (a *Aggregate) WriteConcern(writeConcern *writeconcern.WriteConcern) *Aggregate {
   340  	if a == nil {
   341  		a = new(Aggregate)
   342  	}
   343  
   344  	a.writeConcern = writeConcern
   345  	return a
   346  }
   347  
   348  // Retry enables retryable writes for this operation. Retries are not handled automatically,
   349  // instead a boolean is returned from Execute and SelectAndExecute that indicates if the
   350  // operation can be retried. Retrying is handled by calling RetryExecute.
   351  func (a *Aggregate) Retry(retry driver.RetryMode) *Aggregate {
   352  	if a == nil {
   353  		a = new(Aggregate)
   354  	}
   355  
   356  	a.retry = &retry
   357  	return a
   358  }
   359  
   360  // Crypt sets the Crypt object to use for automatic encryption and decryption.
   361  func (a *Aggregate) Crypt(crypt driver.Crypt) *Aggregate {
   362  	if a == nil {
   363  		a = new(Aggregate)
   364  	}
   365  
   366  	a.crypt = crypt
   367  	return a
   368  }
   369  
   370  // ServerAPI sets the server API version for this operation.
   371  func (a *Aggregate) ServerAPI(serverAPI *driver.ServerAPIOptions) *Aggregate {
   372  	if a == nil {
   373  		a = new(Aggregate)
   374  	}
   375  
   376  	a.serverAPI = serverAPI
   377  	return a
   378  }
   379  
   380  // Let specifies the let document to use. This option is only valid for server versions 5.0 and above.
   381  func (a *Aggregate) Let(let bsoncore.Document) *Aggregate {
   382  	if a == nil {
   383  		a = new(Aggregate)
   384  	}
   385  
   386  	a.let = let
   387  	return a
   388  }
   389  
   390  // HasOutputStage specifies whether the aggregate contains an output stage. Used in determining when to
   391  // append read preference at the operation level.
   392  func (a *Aggregate) HasOutputStage(hos bool) *Aggregate {
   393  	if a == nil {
   394  		a = new(Aggregate)
   395  	}
   396  
   397  	a.hasOutputStage = hos
   398  	return a
   399  }
   400  
   401  // CustomOptions specifies extra options to use in the aggregate command.
   402  func (a *Aggregate) CustomOptions(co map[string]bsoncore.Value) *Aggregate {
   403  	if a == nil {
   404  		a = new(Aggregate)
   405  	}
   406  
   407  	a.customOptions = co
   408  	return a
   409  }
   410  
   411  // Timeout sets the timeout for this operation.
   412  func (a *Aggregate) Timeout(timeout *time.Duration) *Aggregate {
   413  	if a == nil {
   414  		a = new(Aggregate)
   415  	}
   416  
   417  	a.timeout = timeout
   418  	return a
   419  }