...

Source file src/go.mongodb.org/mongo-driver/x/mongo/driver/operation/delete.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  	"fmt"
    13  	"time"
    14  
    15  	"go.mongodb.org/mongo-driver/bson/bsontype"
    16  	"go.mongodb.org/mongo-driver/event"
    17  	"go.mongodb.org/mongo-driver/internal/driverutil"
    18  	"go.mongodb.org/mongo-driver/internal/logger"
    19  	"go.mongodb.org/mongo-driver/mongo/description"
    20  	"go.mongodb.org/mongo-driver/mongo/writeconcern"
    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  // Delete performs a delete operation
    27  type Delete struct {
    28  	comment      bsoncore.Value
    29  	deletes      []bsoncore.Document
    30  	ordered      *bool
    31  	session      *session.Client
    32  	clock        *session.ClusterClock
    33  	collection   string
    34  	monitor      *event.CommandMonitor
    35  	crypt        driver.Crypt
    36  	database     string
    37  	deployment   driver.Deployment
    38  	selector     description.ServerSelector
    39  	writeConcern *writeconcern.WriteConcern
    40  	retry        *driver.RetryMode
    41  	hint         *bool
    42  	result       DeleteResult
    43  	serverAPI    *driver.ServerAPIOptions
    44  	let          bsoncore.Document
    45  	timeout      *time.Duration
    46  	logger       *logger.Logger
    47  }
    48  
    49  // DeleteResult represents a delete result returned by the server.
    50  type DeleteResult struct {
    51  	// Number of documents successfully deleted.
    52  	N int64
    53  }
    54  
    55  func buildDeleteResult(response bsoncore.Document) (DeleteResult, error) {
    56  	elements, err := response.Elements()
    57  	if err != nil {
    58  		return DeleteResult{}, err
    59  	}
    60  	dr := DeleteResult{}
    61  	for _, element := range elements {
    62  		switch element.Key() {
    63  		case "n":
    64  			var ok bool
    65  			dr.N, ok = element.Value().AsInt64OK()
    66  			if !ok {
    67  				return dr, fmt.Errorf("response field 'n' is type int32 or int64, but received BSON type %s", element.Value().Type)
    68  			}
    69  		}
    70  	}
    71  	return dr, nil
    72  }
    73  
    74  // NewDelete constructs and returns a new Delete.
    75  func NewDelete(deletes ...bsoncore.Document) *Delete {
    76  	return &Delete{
    77  		deletes: deletes,
    78  	}
    79  }
    80  
    81  // Result returns the result of executing this operation.
    82  func (d *Delete) Result() DeleteResult { return d.result }
    83  
    84  func (d *Delete) processResponse(info driver.ResponseInfo) error {
    85  	dr, err := buildDeleteResult(info.ServerResponse)
    86  	d.result.N += dr.N
    87  	return err
    88  }
    89  
    90  // Execute runs this operations and returns an error if the operation did not execute successfully.
    91  func (d *Delete) Execute(ctx context.Context) error {
    92  	if d.deployment == nil {
    93  		return errors.New("the Delete operation must have a Deployment set before Execute can be called")
    94  	}
    95  	batches := &driver.Batches{
    96  		Identifier: "deletes",
    97  		Documents:  d.deletes,
    98  		Ordered:    d.ordered,
    99  	}
   100  
   101  	return driver.Operation{
   102  		CommandFn:         d.command,
   103  		ProcessResponseFn: d.processResponse,
   104  		Batches:           batches,
   105  		RetryMode:         d.retry,
   106  		Type:              driver.Write,
   107  		Client:            d.session,
   108  		Clock:             d.clock,
   109  		CommandMonitor:    d.monitor,
   110  		Crypt:             d.crypt,
   111  		Database:          d.database,
   112  		Deployment:        d.deployment,
   113  		Selector:          d.selector,
   114  		WriteConcern:      d.writeConcern,
   115  		ServerAPI:         d.serverAPI,
   116  		Timeout:           d.timeout,
   117  		Logger:            d.logger,
   118  		Name:              driverutil.DeleteOp,
   119  	}.Execute(ctx)
   120  
   121  }
   122  
   123  func (d *Delete) command(dst []byte, desc description.SelectedServer) ([]byte, error) {
   124  	dst = bsoncore.AppendStringElement(dst, "delete", d.collection)
   125  	if d.comment.Type != bsontype.Type(0) {
   126  		dst = bsoncore.AppendValueElement(dst, "comment", d.comment)
   127  	}
   128  	if d.ordered != nil {
   129  		dst = bsoncore.AppendBooleanElement(dst, "ordered", *d.ordered)
   130  	}
   131  	if d.hint != nil && *d.hint {
   132  		if desc.WireVersion == nil || !desc.WireVersion.Includes(5) {
   133  			return nil, errors.New("the 'hint' command parameter requires a minimum server wire version of 5")
   134  		}
   135  		if !d.writeConcern.Acknowledged() {
   136  			return nil, errUnacknowledgedHint
   137  		}
   138  	}
   139  	if d.let != nil {
   140  		dst = bsoncore.AppendDocumentElement(dst, "let", d.let)
   141  	}
   142  	return dst, nil
   143  }
   144  
   145  // Deletes adds documents to this operation that will be used to determine what documents to delete when this operation
   146  // is executed. These documents should have the form {q: <query>, limit: <integer limit>, collation: <document>}. The
   147  // collation field is optional. If limit is 0, there will be no limit on the number of documents deleted.
   148  func (d *Delete) Deletes(deletes ...bsoncore.Document) *Delete {
   149  	if d == nil {
   150  		d = new(Delete)
   151  	}
   152  
   153  	d.deletes = deletes
   154  	return d
   155  }
   156  
   157  // Ordered sets ordered. If true, when a write fails, the operation will return the error, when
   158  // false write failures do not stop execution of the operation.
   159  func (d *Delete) Ordered(ordered bool) *Delete {
   160  	if d == nil {
   161  		d = new(Delete)
   162  	}
   163  
   164  	d.ordered = &ordered
   165  	return d
   166  }
   167  
   168  // Session sets the session for this operation.
   169  func (d *Delete) Session(session *session.Client) *Delete {
   170  	if d == nil {
   171  		d = new(Delete)
   172  	}
   173  
   174  	d.session = session
   175  	return d
   176  }
   177  
   178  // ClusterClock sets the cluster clock for this operation.
   179  func (d *Delete) ClusterClock(clock *session.ClusterClock) *Delete {
   180  	if d == nil {
   181  		d = new(Delete)
   182  	}
   183  
   184  	d.clock = clock
   185  	return d
   186  }
   187  
   188  // Collection sets the collection that this command will run against.
   189  func (d *Delete) Collection(collection string) *Delete {
   190  	if d == nil {
   191  		d = new(Delete)
   192  	}
   193  
   194  	d.collection = collection
   195  	return d
   196  }
   197  
   198  // Comment sets a value to help trace an operation.
   199  func (d *Delete) Comment(comment bsoncore.Value) *Delete {
   200  	if d == nil {
   201  		d = new(Delete)
   202  	}
   203  
   204  	d.comment = comment
   205  	return d
   206  }
   207  
   208  // CommandMonitor sets the monitor to use for APM events.
   209  func (d *Delete) CommandMonitor(monitor *event.CommandMonitor) *Delete {
   210  	if d == nil {
   211  		d = new(Delete)
   212  	}
   213  
   214  	d.monitor = monitor
   215  	return d
   216  }
   217  
   218  // Crypt sets the Crypt object to use for automatic encryption and decryption.
   219  func (d *Delete) Crypt(crypt driver.Crypt) *Delete {
   220  	if d == nil {
   221  		d = new(Delete)
   222  	}
   223  
   224  	d.crypt = crypt
   225  	return d
   226  }
   227  
   228  // Database sets the database to run this operation against.
   229  func (d *Delete) Database(database string) *Delete {
   230  	if d == nil {
   231  		d = new(Delete)
   232  	}
   233  
   234  	d.database = database
   235  	return d
   236  }
   237  
   238  // Deployment sets the deployment to use for this operation.
   239  func (d *Delete) Deployment(deployment driver.Deployment) *Delete {
   240  	if d == nil {
   241  		d = new(Delete)
   242  	}
   243  
   244  	d.deployment = deployment
   245  	return d
   246  }
   247  
   248  // ServerSelector sets the selector used to retrieve a server.
   249  func (d *Delete) ServerSelector(selector description.ServerSelector) *Delete {
   250  	if d == nil {
   251  		d = new(Delete)
   252  	}
   253  
   254  	d.selector = selector
   255  	return d
   256  }
   257  
   258  // WriteConcern sets the write concern for this operation.
   259  func (d *Delete) WriteConcern(writeConcern *writeconcern.WriteConcern) *Delete {
   260  	if d == nil {
   261  		d = new(Delete)
   262  	}
   263  
   264  	d.writeConcern = writeConcern
   265  	return d
   266  }
   267  
   268  // Retry enables retryable mode for this operation. Retries are handled automatically in driver.Operation.Execute based
   269  // on how the operation is set.
   270  func (d *Delete) Retry(retry driver.RetryMode) *Delete {
   271  	if d == nil {
   272  		d = new(Delete)
   273  	}
   274  
   275  	d.retry = &retry
   276  	return d
   277  }
   278  
   279  // Hint is a flag to indicate that the update document contains a hint. Hint is only supported by
   280  // servers >= 4.4. Older servers >= 3.4 will report an error for using the hint option. For servers <
   281  // 3.4, the driver will return an error if the hint option is used.
   282  func (d *Delete) Hint(hint bool) *Delete {
   283  	if d == nil {
   284  		d = new(Delete)
   285  	}
   286  
   287  	d.hint = &hint
   288  	return d
   289  }
   290  
   291  // ServerAPI sets the server API version for this operation.
   292  func (d *Delete) ServerAPI(serverAPI *driver.ServerAPIOptions) *Delete {
   293  	if d == nil {
   294  		d = new(Delete)
   295  	}
   296  
   297  	d.serverAPI = serverAPI
   298  	return d
   299  }
   300  
   301  // Let specifies the let document to use. This option is only valid for server versions 5.0 and above.
   302  func (d *Delete) Let(let bsoncore.Document) *Delete {
   303  	if d == nil {
   304  		d = new(Delete)
   305  	}
   306  
   307  	d.let = let
   308  	return d
   309  }
   310  
   311  // Timeout sets the timeout for this operation.
   312  func (d *Delete) Timeout(timeout *time.Duration) *Delete {
   313  	if d == nil {
   314  		d = new(Delete)
   315  	}
   316  
   317  	d.timeout = timeout
   318  	return d
   319  }
   320  
   321  // Logger sets the logger for this operation.
   322  func (d *Delete) Logger(logger *logger.Logger) *Delete {
   323  	if d == nil {
   324  		d = new(Delete)
   325  	}
   326  
   327  	d.logger = logger
   328  
   329  	return d
   330  }
   331  

View as plain text