...

Source file src/go.mongodb.org/mongo-driver/x/mongo/driver/operation/find.go

Documentation: go.mongodb.org/mongo-driver/x/mongo/driver/operation

     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/internal/driverutil"
    17  	"go.mongodb.org/mongo-driver/internal/logger"
    18  	"go.mongodb.org/mongo-driver/mongo/description"
    19  	"go.mongodb.org/mongo-driver/mongo/readconcern"
    20  	"go.mongodb.org/mongo-driver/mongo/readpref"
    21  	"go.mongodb.org/mongo-driver/x/bsonx/bsoncore"
    22  	"go.mongodb.org/mongo-driver/x/mongo/driver"
    23  	"go.mongodb.org/mongo-driver/x/mongo/driver/session"
    24  )
    25  
    26  // Find performs a find operation.
    27  type Find struct {
    28  	allowDiskUse        *bool
    29  	allowPartialResults *bool
    30  	awaitData           *bool
    31  	batchSize           *int32
    32  	collation           bsoncore.Document
    33  	comment             *string
    34  	filter              bsoncore.Document
    35  	hint                bsoncore.Value
    36  	let                 bsoncore.Document
    37  	limit               *int64
    38  	max                 bsoncore.Document
    39  	maxTime             *time.Duration
    40  	min                 bsoncore.Document
    41  	noCursorTimeout     *bool
    42  	oplogReplay         *bool
    43  	projection          bsoncore.Document
    44  	returnKey           *bool
    45  	showRecordID        *bool
    46  	singleBatch         *bool
    47  	skip                *int64
    48  	snapshot            *bool
    49  	sort                bsoncore.Document
    50  	tailable            *bool
    51  	session             *session.Client
    52  	clock               *session.ClusterClock
    53  	collection          string
    54  	monitor             *event.CommandMonitor
    55  	crypt               driver.Crypt
    56  	database            string
    57  	deployment          driver.Deployment
    58  	readConcern         *readconcern.ReadConcern
    59  	readPreference      *readpref.ReadPref
    60  	selector            description.ServerSelector
    61  	retry               *driver.RetryMode
    62  	result              driver.CursorResponse
    63  	serverAPI           *driver.ServerAPIOptions
    64  	timeout             *time.Duration
    65  	omitCSOTMaxTimeMS   bool
    66  	logger              *logger.Logger
    67  }
    68  
    69  // NewFind constructs and returns a new Find.
    70  func NewFind(filter bsoncore.Document) *Find {
    71  	return &Find{
    72  		filter: filter,
    73  	}
    74  }
    75  
    76  // Result returns the result of executing this operation.
    77  func (f *Find) Result(opts driver.CursorOptions) (*driver.BatchCursor, error) {
    78  	opts.ServerAPI = f.serverAPI
    79  	return driver.NewBatchCursor(f.result, f.session, f.clock, opts)
    80  }
    81  
    82  func (f *Find) processResponse(info driver.ResponseInfo) error {
    83  	var err error
    84  	f.result, err = driver.NewCursorResponse(info)
    85  	return err
    86  }
    87  
    88  // Execute runs this operations and returns an error if the operation did not execute successfully.
    89  func (f *Find) Execute(ctx context.Context) error {
    90  	if f.deployment == nil {
    91  		return errors.New("the Find operation must have a Deployment set before Execute can be called")
    92  	}
    93  
    94  	return driver.Operation{
    95  		CommandFn:         f.command,
    96  		ProcessResponseFn: f.processResponse,
    97  		RetryMode:         f.retry,
    98  		Type:              driver.Read,
    99  		Client:            f.session,
   100  		Clock:             f.clock,
   101  		CommandMonitor:    f.monitor,
   102  		Crypt:             f.crypt,
   103  		Database:          f.database,
   104  		Deployment:        f.deployment,
   105  		MaxTime:           f.maxTime,
   106  		ReadConcern:       f.readConcern,
   107  		ReadPreference:    f.readPreference,
   108  		Selector:          f.selector,
   109  		Legacy:            driver.LegacyFind,
   110  		ServerAPI:         f.serverAPI,
   111  		Timeout:           f.timeout,
   112  		Logger:            f.logger,
   113  		Name:              driverutil.FindOp,
   114  		OmitCSOTMaxTimeMS: f.omitCSOTMaxTimeMS,
   115  	}.Execute(ctx)
   116  
   117  }
   118  
   119  func (f *Find) command(dst []byte, desc description.SelectedServer) ([]byte, error) {
   120  	dst = bsoncore.AppendStringElement(dst, "find", f.collection)
   121  	if f.allowDiskUse != nil {
   122  		if desc.WireVersion == nil || !desc.WireVersion.Includes(4) {
   123  			return nil, errors.New("the 'allowDiskUse' command parameter requires a minimum server wire version of 4")
   124  		}
   125  		dst = bsoncore.AppendBooleanElement(dst, "allowDiskUse", *f.allowDiskUse)
   126  	}
   127  	if f.allowPartialResults != nil {
   128  		dst = bsoncore.AppendBooleanElement(dst, "allowPartialResults", *f.allowPartialResults)
   129  	}
   130  	if f.awaitData != nil {
   131  		dst = bsoncore.AppendBooleanElement(dst, "awaitData", *f.awaitData)
   132  	}
   133  	if f.batchSize != nil {
   134  		dst = bsoncore.AppendInt32Element(dst, "batchSize", *f.batchSize)
   135  	}
   136  	if f.collation != nil {
   137  		if desc.WireVersion == nil || !desc.WireVersion.Includes(5) {
   138  			return nil, errors.New("the 'collation' command parameter requires a minimum server wire version of 5")
   139  		}
   140  		dst = bsoncore.AppendDocumentElement(dst, "collation", f.collation)
   141  	}
   142  	if f.comment != nil {
   143  		dst = bsoncore.AppendStringElement(dst, "comment", *f.comment)
   144  	}
   145  	if f.filter != nil {
   146  		dst = bsoncore.AppendDocumentElement(dst, "filter", f.filter)
   147  	}
   148  	if f.hint.Type != bsontype.Type(0) {
   149  		dst = bsoncore.AppendValueElement(dst, "hint", f.hint)
   150  	}
   151  	if f.let != nil {
   152  		dst = bsoncore.AppendDocumentElement(dst, "let", f.let)
   153  	}
   154  	if f.limit != nil {
   155  		dst = bsoncore.AppendInt64Element(dst, "limit", *f.limit)
   156  	}
   157  	if f.max != nil {
   158  		dst = bsoncore.AppendDocumentElement(dst, "max", f.max)
   159  	}
   160  	if f.min != nil {
   161  		dst = bsoncore.AppendDocumentElement(dst, "min", f.min)
   162  	}
   163  	if f.noCursorTimeout != nil {
   164  		dst = bsoncore.AppendBooleanElement(dst, "noCursorTimeout", *f.noCursorTimeout)
   165  	}
   166  	if f.oplogReplay != nil {
   167  		dst = bsoncore.AppendBooleanElement(dst, "oplogReplay", *f.oplogReplay)
   168  	}
   169  	if f.projection != nil {
   170  		dst = bsoncore.AppendDocumentElement(dst, "projection", f.projection)
   171  	}
   172  	if f.returnKey != nil {
   173  		dst = bsoncore.AppendBooleanElement(dst, "returnKey", *f.returnKey)
   174  	}
   175  	if f.showRecordID != nil {
   176  		dst = bsoncore.AppendBooleanElement(dst, "showRecordId", *f.showRecordID)
   177  	}
   178  	if f.singleBatch != nil {
   179  		dst = bsoncore.AppendBooleanElement(dst, "singleBatch", *f.singleBatch)
   180  	}
   181  	if f.skip != nil {
   182  		dst = bsoncore.AppendInt64Element(dst, "skip", *f.skip)
   183  	}
   184  	if f.snapshot != nil {
   185  		dst = bsoncore.AppendBooleanElement(dst, "snapshot", *f.snapshot)
   186  	}
   187  	if f.sort != nil {
   188  		dst = bsoncore.AppendDocumentElement(dst, "sort", f.sort)
   189  	}
   190  	if f.tailable != nil {
   191  		dst = bsoncore.AppendBooleanElement(dst, "tailable", *f.tailable)
   192  	}
   193  	return dst, nil
   194  }
   195  
   196  // AllowDiskUse when true allows temporary data to be written to disk during the find command."
   197  func (f *Find) AllowDiskUse(allowDiskUse bool) *Find {
   198  	if f == nil {
   199  		f = new(Find)
   200  	}
   201  
   202  	f.allowDiskUse = &allowDiskUse
   203  	return f
   204  }
   205  
   206  // AllowPartialResults when true allows partial results to be returned if some shards are down.
   207  func (f *Find) AllowPartialResults(allowPartialResults bool) *Find {
   208  	if f == nil {
   209  		f = new(Find)
   210  	}
   211  
   212  	f.allowPartialResults = &allowPartialResults
   213  	return f
   214  }
   215  
   216  // AwaitData when true makes a cursor block before returning when no data is available.
   217  func (f *Find) AwaitData(awaitData bool) *Find {
   218  	if f == nil {
   219  		f = new(Find)
   220  	}
   221  
   222  	f.awaitData = &awaitData
   223  	return f
   224  }
   225  
   226  // BatchSize specifies the number of documents to return in every batch.
   227  func (f *Find) BatchSize(batchSize int32) *Find {
   228  	if f == nil {
   229  		f = new(Find)
   230  	}
   231  
   232  	f.batchSize = &batchSize
   233  	return f
   234  }
   235  
   236  // Collation specifies a collation to be used.
   237  func (f *Find) Collation(collation bsoncore.Document) *Find {
   238  	if f == nil {
   239  		f = new(Find)
   240  	}
   241  
   242  	f.collation = collation
   243  	return f
   244  }
   245  
   246  // Comment sets a string to help trace an operation.
   247  func (f *Find) Comment(comment string) *Find {
   248  	if f == nil {
   249  		f = new(Find)
   250  	}
   251  
   252  	f.comment = &comment
   253  	return f
   254  }
   255  
   256  // Filter determines what results are returned from find.
   257  func (f *Find) Filter(filter bsoncore.Document) *Find {
   258  	if f == nil {
   259  		f = new(Find)
   260  	}
   261  
   262  	f.filter = filter
   263  	return f
   264  }
   265  
   266  // Hint specifies the index to use.
   267  func (f *Find) Hint(hint bsoncore.Value) *Find {
   268  	if f == nil {
   269  		f = new(Find)
   270  	}
   271  
   272  	f.hint = hint
   273  	return f
   274  }
   275  
   276  // Let specifies the let document to use. This option is only valid for server versions 5.0 and above.
   277  func (f *Find) Let(let bsoncore.Document) *Find {
   278  	if f == nil {
   279  		f = new(Find)
   280  	}
   281  
   282  	f.let = let
   283  	return f
   284  }
   285  
   286  // Limit sets a limit on the number of documents to return.
   287  func (f *Find) Limit(limit int64) *Find {
   288  	if f == nil {
   289  		f = new(Find)
   290  	}
   291  
   292  	f.limit = &limit
   293  	return f
   294  }
   295  
   296  // Max sets an exclusive upper bound for a specific index.
   297  func (f *Find) Max(max bsoncore.Document) *Find {
   298  	if f == nil {
   299  		f = new(Find)
   300  	}
   301  
   302  	f.max = max
   303  	return f
   304  }
   305  
   306  // MaxTime specifies the maximum amount of time to allow the query to run on the server.
   307  func (f *Find) MaxTime(maxTime *time.Duration) *Find {
   308  	if f == nil {
   309  		f = new(Find)
   310  	}
   311  
   312  	f.maxTime = maxTime
   313  	return f
   314  }
   315  
   316  // Min sets an inclusive lower bound for a specific index.
   317  func (f *Find) Min(min bsoncore.Document) *Find {
   318  	if f == nil {
   319  		f = new(Find)
   320  	}
   321  
   322  	f.min = min
   323  	return f
   324  }
   325  
   326  // NoCursorTimeout when true prevents cursor from timing out after an inactivity period.
   327  func (f *Find) NoCursorTimeout(noCursorTimeout bool) *Find {
   328  	if f == nil {
   329  		f = new(Find)
   330  	}
   331  
   332  	f.noCursorTimeout = &noCursorTimeout
   333  	return f
   334  }
   335  
   336  // OplogReplay when true replays a replica set's oplog.
   337  func (f *Find) OplogReplay(oplogReplay bool) *Find {
   338  	if f == nil {
   339  		f = new(Find)
   340  	}
   341  
   342  	f.oplogReplay = &oplogReplay
   343  	return f
   344  }
   345  
   346  // Projection limits the fields returned for all documents.
   347  func (f *Find) Projection(projection bsoncore.Document) *Find {
   348  	if f == nil {
   349  		f = new(Find)
   350  	}
   351  
   352  	f.projection = projection
   353  	return f
   354  }
   355  
   356  // ReturnKey when true returns index keys for all result documents.
   357  func (f *Find) ReturnKey(returnKey bool) *Find {
   358  	if f == nil {
   359  		f = new(Find)
   360  	}
   361  
   362  	f.returnKey = &returnKey
   363  	return f
   364  }
   365  
   366  // ShowRecordID when true adds a $recordId field with the record identifier to returned documents.
   367  func (f *Find) ShowRecordID(showRecordID bool) *Find {
   368  	if f == nil {
   369  		f = new(Find)
   370  	}
   371  
   372  	f.showRecordID = &showRecordID
   373  	return f
   374  }
   375  
   376  // SingleBatch specifies whether the results should be returned in a single batch.
   377  func (f *Find) SingleBatch(singleBatch bool) *Find {
   378  	if f == nil {
   379  		f = new(Find)
   380  	}
   381  
   382  	f.singleBatch = &singleBatch
   383  	return f
   384  }
   385  
   386  // Skip specifies the number of documents to skip before returning.
   387  func (f *Find) Skip(skip int64) *Find {
   388  	if f == nil {
   389  		f = new(Find)
   390  	}
   391  
   392  	f.skip = &skip
   393  	return f
   394  }
   395  
   396  // Snapshot prevents the cursor from returning a document more than once because of an intervening write operation.
   397  func (f *Find) Snapshot(snapshot bool) *Find {
   398  	if f == nil {
   399  		f = new(Find)
   400  	}
   401  
   402  	f.snapshot = &snapshot
   403  	return f
   404  }
   405  
   406  // Sort specifies the order in which to return results.
   407  func (f *Find) Sort(sort bsoncore.Document) *Find {
   408  	if f == nil {
   409  		f = new(Find)
   410  	}
   411  
   412  	f.sort = sort
   413  	return f
   414  }
   415  
   416  // Tailable keeps a cursor open and resumable after the last data has been retrieved.
   417  func (f *Find) Tailable(tailable bool) *Find {
   418  	if f == nil {
   419  		f = new(Find)
   420  	}
   421  
   422  	f.tailable = &tailable
   423  	return f
   424  }
   425  
   426  // Session sets the session for this operation.
   427  func (f *Find) Session(session *session.Client) *Find {
   428  	if f == nil {
   429  		f = new(Find)
   430  	}
   431  
   432  	f.session = session
   433  	return f
   434  }
   435  
   436  // ClusterClock sets the cluster clock for this operation.
   437  func (f *Find) ClusterClock(clock *session.ClusterClock) *Find {
   438  	if f == nil {
   439  		f = new(Find)
   440  	}
   441  
   442  	f.clock = clock
   443  	return f
   444  }
   445  
   446  // Collection sets the collection that this command will run against.
   447  func (f *Find) Collection(collection string) *Find {
   448  	if f == nil {
   449  		f = new(Find)
   450  	}
   451  
   452  	f.collection = collection
   453  	return f
   454  }
   455  
   456  // CommandMonitor sets the monitor to use for APM events.
   457  func (f *Find) CommandMonitor(monitor *event.CommandMonitor) *Find {
   458  	if f == nil {
   459  		f = new(Find)
   460  	}
   461  
   462  	f.monitor = monitor
   463  	return f
   464  }
   465  
   466  // Crypt sets the Crypt object to use for automatic encryption and decryption.
   467  func (f *Find) Crypt(crypt driver.Crypt) *Find {
   468  	if f == nil {
   469  		f = new(Find)
   470  	}
   471  
   472  	f.crypt = crypt
   473  	return f
   474  }
   475  
   476  // Database sets the database to run this operation against.
   477  func (f *Find) Database(database string) *Find {
   478  	if f == nil {
   479  		f = new(Find)
   480  	}
   481  
   482  	f.database = database
   483  	return f
   484  }
   485  
   486  // Deployment sets the deployment to use for this operation.
   487  func (f *Find) Deployment(deployment driver.Deployment) *Find {
   488  	if f == nil {
   489  		f = new(Find)
   490  	}
   491  
   492  	f.deployment = deployment
   493  	return f
   494  }
   495  
   496  // ReadConcern specifies the read concern for this operation.
   497  func (f *Find) ReadConcern(readConcern *readconcern.ReadConcern) *Find {
   498  	if f == nil {
   499  		f = new(Find)
   500  	}
   501  
   502  	f.readConcern = readConcern
   503  	return f
   504  }
   505  
   506  // ReadPreference set the read preference used with this operation.
   507  func (f *Find) ReadPreference(readPreference *readpref.ReadPref) *Find {
   508  	if f == nil {
   509  		f = new(Find)
   510  	}
   511  
   512  	f.readPreference = readPreference
   513  	return f
   514  }
   515  
   516  // ServerSelector sets the selector used to retrieve a server.
   517  func (f *Find) ServerSelector(selector description.ServerSelector) *Find {
   518  	if f == nil {
   519  		f = new(Find)
   520  	}
   521  
   522  	f.selector = selector
   523  	return f
   524  }
   525  
   526  // Retry enables retryable mode for this operation. Retries are handled automatically in driver.Operation.Execute based
   527  // on how the operation is set.
   528  func (f *Find) Retry(retry driver.RetryMode) *Find {
   529  	if f == nil {
   530  		f = new(Find)
   531  	}
   532  
   533  	f.retry = &retry
   534  	return f
   535  }
   536  
   537  // ServerAPI sets the server API version for this operation.
   538  func (f *Find) ServerAPI(serverAPI *driver.ServerAPIOptions) *Find {
   539  	if f == nil {
   540  		f = new(Find)
   541  	}
   542  
   543  	f.serverAPI = serverAPI
   544  	return f
   545  }
   546  
   547  // Timeout sets the timeout for this operation.
   548  func (f *Find) Timeout(timeout *time.Duration) *Find {
   549  	if f == nil {
   550  		f = new(Find)
   551  	}
   552  
   553  	f.timeout = timeout
   554  	return f
   555  }
   556  
   557  // OmitCSOTMaxTimeMS omits the automatically-calculated "maxTimeMS" from the
   558  // command when CSOT is enabled. It does not effect "maxTimeMS" set by
   559  // [Find.MaxTime].
   560  func (f *Find) OmitCSOTMaxTimeMS(omit bool) *Find {
   561  	if f == nil {
   562  		f = new(Find)
   563  	}
   564  
   565  	f.omitCSOTMaxTimeMS = omit
   566  	return f
   567  }
   568  
   569  // Logger sets the logger for this operation.
   570  func (f *Find) Logger(logger *logger.Logger) *Find {
   571  	if f == nil {
   572  		f = new(Find)
   573  	}
   574  
   575  	f.logger = logger
   576  	return f
   577  }
   578  

View as plain text