1# Copyright 2014 - present MongoDB, Inc. 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15use strict; 16use warnings; 17package MongoDB::BulkWriteView; 18 19# ABSTRACT: Bulk write operations against a query document 20 21use version; 22our $VERSION = 'v2.2.2'; 23 24use Moo; 25 26use MongoDB::Error; 27use MongoDB::_Types qw( 28 Boolish 29 Document 30 IxHash 31); 32use Types::Standard qw( 33 Maybe 34 ArrayRef 35 InstanceOf 36); 37use boolean; 38use namespace::clean -except => 'meta'; 39 40# A hash reference containing a MongoDB query document 41has _query => ( 42 is => 'ro', 43 isa => IxHash, 44 coerce => IxHash->coercion, 45 required => 1 46); 47 48# Originating bulk write object for executing write operations. 49has _bulk => ( 50 is => 'ro', 51 isa => InstanceOf['MongoDB::BulkWrite'], 52 required => 1, 53 handles => [qw/_enqueue_write/] 54); 55 56has _collation => ( 57 is => 'ro', 58 isa => Maybe [Document], 59); 60 61has _array_filters => ( 62 is => 'ro', 63 isa => Maybe [ArrayRef[Document]], 64); 65 66has _upsert => ( 67 is => 'ro', 68 isa => Boolish, 69 default => 0, 70); 71 72sub collation { 73 my ($self, $collation) = @_; 74 return $self->new( %$self, _collation => $collation ); 75} 76 77sub arrayFilters { 78 my ( $self, $array_filters ) = @_; 79 return $self->new( %$self, _array_filters => $array_filters ); 80} 81 82sub upsert { 83 my ($self) = @_; 84 unless ( @_ == 1 ) { 85 MongoDB::UsageError->throw("the upsert method takes no arguments"); 86 } 87 return $self->new( %$self, _upsert => true ); 88} 89 90sub update_many { 91 push @_, "update_many"; 92 goto &_update; 93} 94 95sub update_one { 96 push @_, "update_one"; 97 goto &_update; 98} 99 100sub replace_one { 101 push @_, "replace_one"; 102 goto &_update; 103} 104 105sub _update { 106 my $method = pop @_; 107 my ( $self, $doc ) = @_; 108 109 my $type = ref $doc; 110 unless ( @_ == 2 && grep { $type eq $_ } qw/HASH ARRAY Tie::IxHash BSON::Array/ ) { 111 MongoDB::UsageError->throw("argument to $method must be a single hashref, arrayref, Tie::IxHash or BSON::Array"); 112 } 113 114 if ( ref $doc eq 'ARRAY' ) { 115 MongoDB::UsageError->throw("array reference to $method must have key/value pairs") 116 if @$doc % 2; 117 $doc = Tie::IxHash->new(@$doc); 118 } 119 elsif ( ref $doc eq 'HASH' ) { 120 $doc = Tie::IxHash->new(%$doc); 121 } 122 123 $self->_bulk->_retryable( 0 ) if $method eq 'update_many'; 124 125 my $update = { 126 q => $self->_query, 127 u => $doc, 128 multi => $method eq 'update_many' ? true : false, 129 upsert => boolean( $self->_upsert ), 130 is_replace => $method eq 'replace_one', 131 (defined $self->_collation ? (collation => $self->_collation) : ()), 132 (defined $self->_array_filters ? (arrayFilters => $self->_array_filters) : ()), 133 }; 134 135 $self->_enqueue_write( [ update => $update ] ); 136 137 return; 138} 139 140sub delete_many { 141 my ($self) = @_; 142 $self->_bulk->_retryable( 0 ); 143 $self->_enqueue_write( 144 [ 145 delete => { 146 q => $self->_query, 147 limit => 0, 148 ( defined $self->_collation ? ( collation => $self->_collation ) : () ), 149 (defined $self->_array_filters ? (arrayFilters => $self->_array_filters) : ()), 150 } 151 ] 152 ); 153 return; 154} 155 156sub delete_one { 157 my ($self) = @_; 158 $self->_enqueue_write( 159 [ 160 delete => { 161 q => $self->_query, 162 limit => 1, 163 ( defined $self->_collation ? ( collation => $self->_collation ) : () ), 164 (defined $self->_array_filters ? (arrayFilters => $self->_array_filters) : ()), 165 } 166 ] 167 ); 168 return; 169} 170 1711; 172 173__END__ 174 175=pod 176 177=encoding UTF-8 178 179=head1 NAME 180 181MongoDB::BulkWriteView - Bulk write operations against a query document 182 183=head1 VERSION 184 185version v2.2.2 186 187=head1 SYNOPSIS 188 189 my $bulk = $collection->initialize_ordered_bulk_op; 190 191 # Update one document matching the selector 192 bulk->find( { a => 1 } )->update_one( { '$inc' => { x => 1 } } ); 193 194 # Update all documents matching the selector 195 bulk->find( { a => 2 } )->update_many( { '$inc' => { x => 2 } } ); 196 197 # Update all documents matching the selector, with respect to a collation 198 bulk->find( { a => { '$gte' => 'F' } )->collation($collation) 199 ->update_many( { '$inc' => { x => 2 } } ); 200 201 # Update all documents 202 bulk->find( {} )->update_many( { '$inc' => { x => 2 } } ); 203 204 # Replace entire document (update with whole doc replace) 205 bulk->find( { a => 3 } )->replace_one( { x => 3 } ); 206 207 # Update one document matching the selector or upsert 208 bulk->find( { a => 1 } )->upsert()->update_one( { '$inc' => { x => 1 } } ); 209 210 # Update all documents matching the selector or upsert 211 bulk->find( { a => 2 } )->upsert()->update_many( { '$inc' => { x => 2 } } ); 212 213 # Replaces a single document matching the selector or upsert 214 bulk->find( { a => 3 } )->upsert()->replace_one( { x => 3 } ); 215 216 # Remove a single document matching the selector 217 bulk->find( { a => 4 } )->delete_one(); 218 219 # Remove all documents matching the selector 220 bulk->find( { a => 5 } )->delete_many(); 221 222 # Update any arrays with the matching filter 223 bulk->find( {} )->arrayFilters([ { 'i.b' => 1 } ])->update_many( { '$set' => { 'y.$[i].b' => 2 } } ); 224 225 # Remove all documents matching the selector, with respect to a collation 226 bulk->find( { a => { '$gte' => 'F' } )->collation($collation)->delete_many(); 227 228 # Remove all documents 229 bulk->find( {} )->delete_many(); 230 231=head1 DESCRIPTION 232 233This class provides means to specify write operations constrained by a query 234document. 235 236To instantiate a C<MongoDB::BulkWriteView>, use the L<find|MongoDB::BulkWrite/find> 237method from L<MongoDB::BulkWrite>. 238 239Except for L</arrayFilters>, L</collation> and L</upsert>, all methods have an 240empty return on success; an exception will be thrown on error. 241 242=head1 METHODS 243 244=head2 arrayFilters 245 246 $bulk->arrayFilters( $array_filters )->update_many( $modification ); 247 248Returns a new C<MongoDB::BulkWriteView> object, where the specified arrayFilter 249will be used to determine which array elements to modify for an update 250operation on an array field. 251 252=head2 collation 253 254 $bulk->collation( $collation )->delete_one; 255 256Returns a new C<MongoDB::BulkWriteView> object, where the specified 257collation will be used to determine which documents match the query 258document. A collation can be specified for any deletion, replacement, 259or update. 260 261=head2 delete_many 262 263 $bulk->delete_many; 264 265Removes all documents matching the query document. 266 267=head2 delete_one 268 269 $bulk->delete_one; 270 271Removes a single document matching the query document. 272 273=head2 replace_one 274 275 $bulk->replace_one( $doc ); 276 277Replaces the document matching the query document. The document 278to replace must not have any keys that begin with a dollar sign, C<$>. 279 280=head2 update_many 281 282 $bulk->update_many( $modification ); 283 284Updates all documents matching the query document. The modification 285document must have all its keys begin with a dollar sign, C<$>. 286 287=head2 update_one 288 289 $bulk->update_one( $modification ); 290 291Updates a single document matching the query document. The modification 292document must have all its keys begin with a dollar sign, C<$>. 293 294=head2 upsert 295 296 $bulk->upsert->replace_one( $doc ); 297 298Returns a new C<MongoDB::BulkWriteView> object that will treat every 299update, update_one or replace_one operation as an upsert operation. 300 301=head1 AUTHORS 302 303=over 4 304 305=item * 306 307David Golden <david@mongodb.com> 308 309=item * 310 311Rassi <rassi@mongodb.com> 312 313=item * 314 315Mike Friedman <friedo@friedo.com> 316 317=item * 318 319Kristina Chodorow <k.chodorow@gmail.com> 320 321=item * 322 323Florian Ragwitz <rafl@debian.org> 324 325=back 326 327=head1 COPYRIGHT AND LICENSE 328 329This software is Copyright (c) 2020 by MongoDB, Inc. 330 331This is free software, licensed under: 332 333 The Apache License, Version 2.0, January 2004 334 335=cut 336