From 4f2a8dfd08de21b68335fa9a420704940d644657 Mon Sep 17 00:00:00 2001 From: Dog <296404875@qq.com> Date: Mon, 22 Jul 2024 21:14:07 +0800 Subject: [PATCH] Added two methods incrementEach and decrementEach (#2550) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add tests on incrementEach/decrementEach * Fix incrementEach to handle null values --------- Co-authored-by: Jérôme Tamarelle --- CHANGELOG.md | 4 +++ src/Query/Builder.php | 28 +++++++++++++++++++++ tests/QueryBuilderTest.php | 50 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b4b539e13..e4108377c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ # Changelog All notable changes to this project will be documented in this file. +## [4.8.0] - next + +* Add `Query\Builder::incrementEach()` and `decrementEach()` methods by @SmallRuralDog in [#2550](https://github.com/mongodb/laravel-mongodb/pull/2550) + ## [4.7.0] - 2024-07-19 * Add `Query\Builder::upsert()` method by @GromNaN in [#3052](https://github.com/mongodb/laravel-mongodb/pull/3052) diff --git a/src/Query/Builder.php b/src/Query/Builder.php index 1d4dcf153..ddc2413d8 100644 --- a/src/Query/Builder.php +++ b/src/Query/Builder.php @@ -787,12 +787,40 @@ public function increment($column, $amount = 1, array $extra = [], array $option return $this->performUpdate($query, $options); } + public function incrementEach(array $columns, array $extra = [], array $options = []) + { + $stage['$addFields'] = $extra; + + // Not using $inc for each column, because it would fail if one column is null. + foreach ($columns as $column => $amount) { + $stage['$addFields'][$column] = [ + '$add' => [$amount, ['$ifNull' => ['$' . $column, 0]]], + ]; + } + + $options = $this->inheritConnectionOptions($options); + + return $this->performUpdate([$stage], $options); + } + /** @inheritdoc */ public function decrement($column, $amount = 1, array $extra = [], array $options = []) { return $this->increment($column, -1 * $amount, $extra, $options); } + /** @inheritdoc */ + public function decrementEach(array $columns, array $extra = [], array $options = []) + { + $decrement = []; + + foreach ($columns as $column => $amount) { + $decrement[$column] = -1 * $amount; + } + + return $this->incrementEach($decrement, $extra, $options); + } + /** @inheritdoc */ public function chunkById($count, callable $callback, $column = '_id', $alias = null) { diff --git a/tests/QueryBuilderTest.php b/tests/QueryBuilderTest.php index 7924e02f3..d819db5cd 100644 --- a/tests/QueryBuilderTest.php +++ b/tests/QueryBuilderTest.php @@ -998,4 +998,54 @@ public function testStringableColumn() $user = DB::collection('users')->where($ageColumn, 29)->first(); $this->assertEquals('John Doe', $user['name']); } + + public function testIncrementEach() + { + DB::collection('users')->insert([ + ['name' => 'John Doe', 'age' => 30, 'note' => 5], + ['name' => 'Jane Doe', 'age' => 10, 'note' => 6], + ['name' => 'Robert Roe', 'age' => null], + ]); + + DB::collection('users')->incrementEach([ + 'age' => 1, + 'note' => 2, + ]); + $user = DB::collection('users')->where('name', 'John Doe')->first(); + $this->assertEquals(31, $user['age']); + $this->assertEquals(7, $user['note']); + + $user = DB::collection('users')->where('name', 'Jane Doe')->first(); + $this->assertEquals(11, $user['age']); + $this->assertEquals(8, $user['note']); + + $user = DB::collection('users')->where('name', 'Robert Roe')->first(); + $this->assertSame(1, $user['age']); + $this->assertSame(2, $user['note']); + + DB::collection('users')->where('name', 'Jane Doe')->incrementEach([ + 'age' => 1, + 'note' => 2, + ], ['extra' => 'foo']); + + $user = DB::collection('users')->where('name', 'Jane Doe')->first(); + $this->assertEquals(12, $user['age']); + $this->assertEquals(10, $user['note']); + $this->assertEquals('foo', $user['extra']); + + $user = DB::collection('users')->where('name', 'John Doe')->first(); + $this->assertEquals(31, $user['age']); + $this->assertEquals(7, $user['note']); + $this->assertArrayNotHasKey('extra', $user); + + DB::collection('users')->decrementEach([ + 'age' => 1, + 'note' => 2, + ], ['extra' => 'foo']); + + $user = DB::collection('users')->where('name', 'John Doe')->first(); + $this->assertEquals(30, $user['age']); + $this->assertEquals(5, $user['note']); + $this->assertEquals('foo', $user['extra']); + } }