QueryBuilderTest.php 26.7 KB
Newer Older
1
<?php
Simon Schaufelberger's avatar
Simon Schaufelberger committed
2
declare(strict_types=1);
3

Simon Schaufelberger's avatar
Simon Schaufelberger committed
4
use Illuminate\Support\Facades\DB;
Jens Segers's avatar
Jens Segers committed
5 6 7
use Jenssegers\Mongodb\Collection;
use Jenssegers\Mongodb\Query\Builder;
use MongoDB\BSON\ObjectId;
8
use MongoDB\BSON\Regex;
Jens Segers's avatar
Jens Segers committed
9 10
use MongoDB\BSON\UTCDateTime;
use MongoDB\Driver\Cursor;
11

Jens Segers's avatar
Jens Segers committed
12 13
class QueryBuilderTest extends TestCase
{
Stas's avatar
Stas committed
14
    public function tearDown(): void
Jens Segers's avatar
Jens Segers committed
15 16 17 18 19
    {
        DB::collection('users')->truncate();
        DB::collection('items')->truncate();
    }

20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
    public function testDeleteWithId()
    {
        $user = DB::collection('users')->insertGetId([
            ['name' => 'Jane Doe', 'age' => 20],
        ]);

        $user_id = (string) $user;

        DB::collection('items')->insert([
            ['name' => 'one thing', 'user_id' => $user_id],
            ['name' => 'last thing', 'user_id' => $user_id],
            ['name' => 'another thing', 'user_id' => $user_id],
            ['name' => 'one more thing', 'user_id' => $user_id],
        ]);

        $product = DB::collection('items')->first();

        $pid = (string) ($product['_id']);

        DB::collection('items')->where('user_id', $user_id)->delete($pid);

        $this->assertEquals(3, DB::collection('items')->count());

        $product = DB::collection('items')->first();

        $pid = $product['_id'];

        DB::collection('items')->where('user_id', $user_id)->delete($pid);

49
        DB::collection('items')->where('user_id', $user_id)->delete(md5('random-id'));
50 51 52 53

        $this->assertEquals(2, DB::collection('items')->count());
    }

Jens Segers's avatar
Jens Segers committed
54 55
    public function testCollection()
    {
Jens Segers's avatar
Jens Segers committed
56
        $this->assertInstanceOf(Builder::class, DB::collection('users'));
Jens Segers's avatar
Jens Segers committed
57 58 59 60 61
    }

    public function testGet()
    {
        $users = DB::collection('users')->get();
Gabriel Caruso's avatar
Gabriel Caruso committed
62
        $this->assertCount(0, $users);
Jens Segers's avatar
Jens Segers committed
63 64 65 66

        DB::collection('users')->insert(['name' => 'John Doe']);

        $users = DB::collection('users')->get();
Gabriel Caruso's avatar
Gabriel Caruso committed
67
        $this->assertCount(1, $users);
Jens Segers's avatar
Jens Segers committed
68 69 70 71
    }

    public function testNoDocument()
    {
Pooya Parsa's avatar
Pooya Parsa committed
72
        $items = DB::collection('items')->where('name', 'nothing')->get()->toArray();
Jens Segers's avatar
Jens Segers committed
73 74 75
        $this->assertEquals([], $items);

        $item = DB::collection('items')->where('name', 'nothing')->first();
Gabriel Caruso's avatar
Gabriel Caruso committed
76
        $this->assertNull($item);
Jens Segers's avatar
Jens Segers committed
77 78

        $item = DB::collection('items')->where('_id', '51c33d8981fec6813e00000a')->first();
Gabriel Caruso's avatar
Gabriel Caruso committed
79
        $this->assertNull($item);
Jens Segers's avatar
Jens Segers committed
80 81 82 83 84 85 86 87 88 89
    }

    public function testInsert()
    {
        DB::collection('users')->insert([
            'tags' => ['tag1', 'tag2'],
            'name' => 'John Doe',
        ]);

        $users = DB::collection('users')->get();
Gabriel Caruso's avatar
Gabriel Caruso committed
90
        $this->assertCount(1, $users);
Jens Segers's avatar
Jens Segers committed
91 92 93

        $user = $users[0];
        $this->assertEquals('John Doe', $user['name']);
94
        $this->assertIsArray($user['tags']);
Jens Segers's avatar
Jens Segers committed
95 96 97 98 99
    }

    public function testInsertGetId()
    {
        $id = DB::collection('users')->insertGetId(['name' => 'John Doe']);
Jens Segers's avatar
Jens Segers committed
100
        $this->assertInstanceOf(ObjectId::class, $id);
Jens Segers's avatar
Jens Segers committed
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
    }

    public function testBatchInsert()
    {
        DB::collection('users')->insert([
            [
                'tags' => ['tag1', 'tag2'],
                'name' => 'Jane Doe',
            ],
            [
                'tags' => ['tag3'],
                'name' => 'John Doe',
            ],
        ]);

        $users = DB::collection('users')->get();
Gabriel Caruso's avatar
Gabriel Caruso committed
117
        $this->assertCount(2, $users);
118
        $this->assertIsArray($users[0]['tags']);
Jens Segers's avatar
Jens Segers committed
119 120 121 122 123 124 125 126 127 128 129 130 131
    }

    public function testFind()
    {
        $id = DB::collection('users')->insertGetId(['name' => 'John Doe']);

        $user = DB::collection('users')->find($id);
        $this->assertEquals('John Doe', $user['name']);
    }

    public function testFindNull()
    {
        $user = DB::collection('users')->find(null);
Gabriel Caruso's avatar
Gabriel Caruso committed
132
        $this->assertNull($user);
Jens Segers's avatar
Jens Segers committed
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
    }

    public function testCount()
    {
        DB::collection('users')->insert([
            ['name' => 'Jane Doe'],
            ['name' => 'John Doe'],
        ]);

        $this->assertEquals(2, DB::collection('users')->count());
    }

    public function testUpdate()
    {
        DB::collection('users')->insert([
            ['name' => 'Jane Doe', 'age' => 20],
            ['name' => 'John Doe', 'age' => 21],
        ]);

        DB::collection('users')->where('name', 'John Doe')->update(['age' => 100]);
        $users = DB::collection('users')->get();

        $john = DB::collection('users')->where('name', 'John Doe')->first();
        $jane = DB::collection('users')->where('name', 'Jane Doe')->first();
        $this->assertEquals(100, $john['age']);
        $this->assertEquals(20, $jane['age']);
    }

    public function testDelete()
    {
        DB::collection('users')->insert([
            ['name' => 'Jane Doe', 'age' => 20],
            ['name' => 'John Doe', 'age' => 25],
        ]);

        DB::collection('users')->where('age', '<', 10)->delete();
        $this->assertEquals(2, DB::collection('users')->count());

        DB::collection('users')->where('age', '<', 25)->delete();
        $this->assertEquals(1, DB::collection('users')->count());
    }

    public function testTruncate()
    {
        DB::collection('users')->insert(['name' => 'John Doe']);
        DB::collection('users')->truncate();
        $this->assertEquals(0, DB::collection('users')->count());
    }

    public function testSubKey()
    {
        DB::collection('users')->insert([
            [
Jens Segers's avatar
Jens Segers committed
186
                'name' => 'John Doe',
Jens Segers's avatar
Jens Segers committed
187 188 189
                'address' => ['country' => 'Belgium', 'city' => 'Ghent'],
            ],
            [
Jens Segers's avatar
Jens Segers committed
190
                'name' => 'Jane Doe',
Jens Segers's avatar
Jens Segers committed
191 192 193 194 195
                'address' => ['country' => 'France', 'city' => 'Paris'],
            ],
        ]);

        $users = DB::collection('users')->where('address.country', 'Belgium')->get();
Gabriel Caruso's avatar
Gabriel Caruso committed
196
        $this->assertCount(1, $users);
Jens Segers's avatar
Jens Segers committed
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211
        $this->assertEquals('John Doe', $users[0]['name']);
    }

    public function testInArray()
    {
        DB::collection('items')->insert([
            [
                'tags' => ['tag1', 'tag2', 'tag3', 'tag4'],
            ],
            [
                'tags' => ['tag2'],
            ],
        ]);

        $items = DB::collection('items')->where('tags', 'tag2')->get();
Gabriel Caruso's avatar
Gabriel Caruso committed
212
        $this->assertCount(2, $items);
Jens Segers's avatar
Jens Segers committed
213 214

        $items = DB::collection('items')->where('tags', 'tag1')->get();
Gabriel Caruso's avatar
Gabriel Caruso committed
215
        $this->assertCount(1, $items);
Jens Segers's avatar
Jens Segers committed
216 217 218 219 220 221 222 223 224
    }

    public function testRaw()
    {
        DB::collection('users')->insert([
            ['name' => 'Jane Doe', 'age' => 20],
            ['name' => 'John Doe', 'age' => 25],
        ]);

Jens Segers's avatar
Jens Segers committed
225
        $cursor = DB::collection('users')->raw(function ($collection) {
Jens Segers's avatar
Jens Segers committed
226 227 228
            return $collection->find(['age' => 20]);
        });

Jens Segers's avatar
Jens Segers committed
229
        $this->assertInstanceOf(Cursor::class, $cursor);
Gabriel Caruso's avatar
Gabriel Caruso committed
230
        $this->assertCount(1, $cursor->toArray());
Jens Segers's avatar
Jens Segers committed
231 232

        $collection = DB::collection('users')->raw();
Jens Segers's avatar
Jens Segers committed
233
        $this->assertInstanceOf(Collection::class, $collection);
Jens Segers's avatar
Jens Segers committed
234 235

        $collection = User::raw();
Jens Segers's avatar
Jens Segers committed
236
        $this->assertInstanceOf(Collection::class, $collection);
Jens Segers's avatar
Jens Segers committed
237 238

        $results = DB::collection('users')->whereRaw(['age' => 20])->get();
Gabriel Caruso's avatar
Gabriel Caruso committed
239
        $this->assertCount(1, $results);
Jens Segers's avatar
Jens Segers committed
240 241 242 243 244 245
        $this->assertEquals('Jane Doe', $results[0]['name']);
    }

    public function testPush()
    {
        $id = DB::collection('users')->insertGetId([
Jens Segers's avatar
Jens Segers committed
246 247
            'name' => 'John Doe',
            'tags' => [],
Jens Segers's avatar
Jens Segers committed
248 249 250 251 252 253
            'messages' => [],
        ]);

        DB::collection('users')->where('_id', $id)->push('tags', 'tag1');

        $user = DB::collection('users')->find($id);
254
        $this->assertIsArray($user['tags']);
Gabriel Caruso's avatar
Gabriel Caruso committed
255
        $this->assertCount(1, $user['tags']);
Jens Segers's avatar
Jens Segers committed
256 257 258 259
        $this->assertEquals('tag1', $user['tags'][0]);

        DB::collection('users')->where('_id', $id)->push('tags', 'tag2');
        $user = DB::collection('users')->find($id);
Gabriel Caruso's avatar
Gabriel Caruso committed
260
        $this->assertCount(2, $user['tags']);
Jens Segers's avatar
Jens Segers committed
261 262 263 264 265
        $this->assertEquals('tag2', $user['tags'][1]);

        // Add duplicate
        DB::collection('users')->where('_id', $id)->push('tags', 'tag2');
        $user = DB::collection('users')->find($id);
Gabriel Caruso's avatar
Gabriel Caruso committed
266
        $this->assertCount(3, $user['tags']);
Jens Segers's avatar
Jens Segers committed
267 268 269 270

        // Add unique
        DB::collection('users')->where('_id', $id)->push('tags', 'tag1', true);
        $user = DB::collection('users')->find($id);
Gabriel Caruso's avatar
Gabriel Caruso committed
271
        $this->assertCount(3, $user['tags']);
Jens Segers's avatar
Jens Segers committed
272 273 274 275

        $message = ['from' => 'Jane', 'body' => 'Hi John'];
        DB::collection('users')->where('_id', $id)->push('messages', $message);
        $user = DB::collection('users')->find($id);
276
        $this->assertIsArray($user['messages']);
Gabriel Caruso's avatar
Gabriel Caruso committed
277
        $this->assertCount(1, $user['messages']);
Jens Segers's avatar
Jens Segers committed
278 279 280
        $this->assertEquals($message, $user['messages'][0]);

        // Raw
Jens Segers's avatar
Jens Segers committed
281 282 283 284
        DB::collection('users')->where('_id', $id)->push([
            'tags' => 'tag3',
            'messages' => ['from' => 'Mark', 'body' => 'Hi John'],
        ]);
Jens Segers's avatar
Jens Segers committed
285
        $user = DB::collection('users')->find($id);
Gabriel Caruso's avatar
Gabriel Caruso committed
286 287
        $this->assertCount(4, $user['tags']);
        $this->assertCount(2, $user['messages']);
Jens Segers's avatar
Jens Segers committed
288

Jens Segers's avatar
Jens Segers committed
289 290 291 292 293 294
        DB::collection('users')->where('_id', $id)->push([
            'messages' => [
                'date' => new DateTime(),
                'body' => 'Hi John',
            ],
        ]);
Jens Segers's avatar
Jens Segers committed
295
        $user = DB::collection('users')->find($id);
Gabriel Caruso's avatar
Gabriel Caruso committed
296
        $this->assertCount(3, $user['messages']);
Jens Segers's avatar
Jens Segers committed
297 298 299 300 301 302 303 304
    }

    public function testPull()
    {
        $message1 = ['from' => 'Jane', 'body' => 'Hi John'];
        $message2 = ['from' => 'Mark', 'body' => 'Hi John'];

        $id = DB::collection('users')->insertGetId([
Jens Segers's avatar
Jens Segers committed
305 306
            'name' => 'John Doe',
            'tags' => ['tag1', 'tag2', 'tag3', 'tag4'],
Jens Segers's avatar
Jens Segers committed
307 308 309 310 311 312
            'messages' => [$message1, $message2],
        ]);

        DB::collection('users')->where('_id', $id)->pull('tags', 'tag3');

        $user = DB::collection('users')->find($id);
313
        $this->assertIsArray($user['tags']);
Gabriel Caruso's avatar
Gabriel Caruso committed
314
        $this->assertCount(3, $user['tags']);
Jens Segers's avatar
Jens Segers committed
315 316 317 318 319
        $this->assertEquals('tag4', $user['tags'][2]);

        DB::collection('users')->where('_id', $id)->pull('messages', $message1);

        $user = DB::collection('users')->find($id);
320
        $this->assertIsArray($user['messages']);
Gabriel Caruso's avatar
Gabriel Caruso committed
321
        $this->assertCount(1, $user['messages']);
Jens Segers's avatar
Jens Segers committed
322 323 324 325

        // Raw
        DB::collection('users')->where('_id', $id)->pull(['tags' => 'tag2', 'messages' => $message2]);
        $user = DB::collection('users')->find($id);
Gabriel Caruso's avatar
Gabriel Caruso committed
326 327
        $this->assertCount(2, $user['tags']);
        $this->assertCount(0, $user['messages']);
Jens Segers's avatar
Jens Segers committed
328 329 330 331 332 333
    }

    public function testDistinct()
    {
        DB::collection('items')->insert([
            ['name' => 'knife', 'type' => 'sharp'],
Jens Segers's avatar
Jens Segers committed
334
            ['name' => 'fork', 'type' => 'sharp'],
Jens Segers's avatar
Jens Segers committed
335 336 337 338
            ['name' => 'spoon', 'type' => 'round'],
            ['name' => 'spoon', 'type' => 'round'],
        ]);

Pooya Parsa's avatar
Pooya Parsa committed
339
        $items = DB::collection('items')->distinct('name')->get()->toArray();
Jens Segers's avatar
Jens Segers committed
340
        sort($items);
Gabriel Caruso's avatar
Gabriel Caruso committed
341
        $this->assertCount(3, $items);
Jens Segers's avatar
Jens Segers committed
342 343
        $this->assertEquals(['fork', 'knife', 'spoon'], $items);

Pooya Parsa's avatar
Pooya Parsa committed
344
        $types = DB::collection('items')->distinct('type')->get()->toArray();
Jens Segers's avatar
Jens Segers committed
345
        sort($types);
Gabriel Caruso's avatar
Gabriel Caruso committed
346
        $this->assertCount(2, $types);
Jens Segers's avatar
Jens Segers committed
347 348 349 350 351 352 353
        $this->assertEquals(['round', 'sharp'], $types);
    }

    public function testCustomId()
    {
        DB::collection('items')->insert([
            ['_id' => 'knife', 'type' => 'sharp', 'amount' => 34],
Jens Segers's avatar
Jens Segers committed
354
            ['_id' => 'fork', 'type' => 'sharp', 'amount' => 20],
Jens Segers's avatar
Jens Segers committed
355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376
            ['_id' => 'spoon', 'type' => 'round', 'amount' => 3],
        ]);

        $item = DB::collection('items')->find('knife');
        $this->assertEquals('knife', $item['_id']);

        $item = DB::collection('items')->where('_id', 'fork')->first();
        $this->assertEquals('fork', $item['_id']);

        DB::collection('users')->insert([
            ['_id' => 1, 'name' => 'Jane Doe'],
            ['_id' => 2, 'name' => 'John Doe'],
        ]);

        $item = DB::collection('users')->find(1);
        $this->assertEquals(1, $item['_id']);
    }

    public function testTake()
    {
        DB::collection('items')->insert([
            ['name' => 'knife', 'type' => 'sharp', 'amount' => 34],
Jens Segers's avatar
Jens Segers committed
377
            ['name' => 'fork', 'type' => 'sharp', 'amount' => 20],
Jens Segers's avatar
Jens Segers committed
378 379 380 381 382
            ['name' => 'spoon', 'type' => 'round', 'amount' => 3],
            ['name' => 'spoon', 'type' => 'round', 'amount' => 14],
        ]);

        $items = DB::collection('items')->orderBy('name')->take(2)->get();
Gabriel Caruso's avatar
Gabriel Caruso committed
383
        $this->assertCount(2, $items);
Jens Segers's avatar
Jens Segers committed
384 385 386 387 388 389 390
        $this->assertEquals('fork', $items[0]['name']);
    }

    public function testSkip()
    {
        DB::collection('items')->insert([
            ['name' => 'knife', 'type' => 'sharp', 'amount' => 34],
Jens Segers's avatar
Jens Segers committed
391
            ['name' => 'fork', 'type' => 'sharp', 'amount' => 20],
Jens Segers's avatar
Jens Segers committed
392 393 394 395 396
            ['name' => 'spoon', 'type' => 'round', 'amount' => 3],
            ['name' => 'spoon', 'type' => 'round', 'amount' => 14],
        ]);

        $items = DB::collection('items')->orderBy('name')->skip(2)->get();
Gabriel Caruso's avatar
Gabriel Caruso committed
397
        $this->assertCount(2, $items);
Jens Segers's avatar
Jens Segers committed
398 399 400 401 402 403 404 405 406 407
        $this->assertEquals('spoon', $items[0]['name']);
    }

    public function testPluck()
    {
        DB::collection('users')->insert([
            ['name' => 'Jane Doe', 'age' => 20],
            ['name' => 'John Doe', 'age' => 25],
        ]);

Pooya Parsa's avatar
Pooya Parsa committed
408
        $age = DB::collection('users')->where('name', 'John Doe')->pluck('age')->toArray();
409
        $this->assertEquals([25], $age);
Jens Segers's avatar
Jens Segers committed
410 411 412 413 414 415
    }

    public function testList()
    {
        DB::collection('items')->insert([
            ['name' => 'knife', 'type' => 'sharp', 'amount' => 34],
Jens Segers's avatar
Jens Segers committed
416
            ['name' => 'fork', 'type' => 'sharp', 'amount' => 20],
Jens Segers's avatar
Jens Segers committed
417 418 419 420
            ['name' => 'spoon', 'type' => 'round', 'amount' => 3],
            ['name' => 'spoon', 'type' => 'round', 'amount' => 14],
        ]);

Pooya Parsa's avatar
Pooya Parsa committed
421
        $list = DB::collection('items')->pluck('name')->toArray();
Jens Segers's avatar
Jens Segers committed
422
        sort($list);
Gabriel Caruso's avatar
Gabriel Caruso committed
423
        $this->assertCount(4, $list);
Jens Segers's avatar
Jens Segers committed
424 425
        $this->assertEquals(['fork', 'knife', 'spoon', 'spoon'], $list);

Pooya Parsa's avatar
Pooya Parsa committed
426
        $list = DB::collection('items')->pluck('type', 'name')->toArray();
Gabriel Caruso's avatar
Gabriel Caruso committed
427
        $this->assertCount(3, $list);
Jens Segers's avatar
Jens Segers committed
428 429
        $this->assertEquals(['knife' => 'sharp', 'fork' => 'sharp', 'spoon' => 'round'], $list);

Pooya Parsa's avatar
Pooya Parsa committed
430
        $list = DB::collection('items')->pluck('name', '_id')->toArray();
Gabriel Caruso's avatar
Gabriel Caruso committed
431
        $this->assertCount(4, $list);
Jens Segers's avatar
Jens Segers committed
432 433 434 435 436 437 438
        $this->assertEquals(24, strlen(key($list)));
    }

    public function testAggregate()
    {
        DB::collection('items')->insert([
            ['name' => 'knife', 'type' => 'sharp', 'amount' => 34],
Jens Segers's avatar
Jens Segers committed
439
            ['name' => 'fork', 'type' => 'sharp', 'amount' => 20],
Jens Segers's avatar
Jens Segers committed
440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457
            ['name' => 'spoon', 'type' => 'round', 'amount' => 3],
            ['name' => 'spoon', 'type' => 'round', 'amount' => 14],
        ]);

        $this->assertEquals(71, DB::collection('items')->sum('amount'));
        $this->assertEquals(4, DB::collection('items')->count('amount'));
        $this->assertEquals(3, DB::collection('items')->min('amount'));
        $this->assertEquals(34, DB::collection('items')->max('amount'));
        $this->assertEquals(17.75, DB::collection('items')->avg('amount'));

        $this->assertEquals(2, DB::collection('items')->where('name', 'spoon')->count('amount'));
        $this->assertEquals(14, DB::collection('items')->where('name', 'spoon')->max('amount'));
    }

    public function testSubdocumentAggregate()
    {
        DB::collection('items')->insert([
            ['name' => 'knife', 'amount' => ['hidden' => 10, 'found' => 3]],
Jens Segers's avatar
Jens Segers committed
458
            ['name' => 'fork', 'amount' => ['hidden' => 35, 'found' => 12]],
Jens Segers's avatar
Jens Segers committed
459 460 461 462 463 464 465 466 467 468 469
            ['name' => 'spoon', 'amount' => ['hidden' => 14, 'found' => 21]],
            ['name' => 'spoon', 'amount' => ['hidden' => 6, 'found' => 4]],
        ]);

        $this->assertEquals(65, DB::collection('items')->sum('amount.hidden'));
        $this->assertEquals(4, DB::collection('items')->count('amount.hidden'));
        $this->assertEquals(6, DB::collection('items')->min('amount.hidden'));
        $this->assertEquals(35, DB::collection('items')->max('amount.hidden'));
        $this->assertEquals(16.25, DB::collection('items')->avg('amount.hidden'));
    }

470 471 472
    public function testSubdocumentArrayAggregate()
    {
        DB::collection('items')->insert([
473
            ['name' => 'knife', 'amount' => [['hidden' => 10, 'found' => 3], ['hidden' => 5, 'found' => 2]]],
Jens Segers's avatar
Jens Segers committed
474 475 476 477 478 479 480 481
            [
                'name' => 'fork',
                'amount' => [
                    ['hidden' => 35, 'found' => 12],
                    ['hidden' => 7, 'found' => 17],
                    ['hidden' => 1, 'found' => 19],
                ],
            ],
482 483 484 485 486 487 488 489 490 491 492
            ['name' => 'spoon', 'amount' => [['hidden' => 14, 'found' => 21]]],
            ['name' => 'teaspoon', 'amount' => []],
        ]);

        $this->assertEquals(72, DB::collection('items')->sum('amount.*.hidden'));
        $this->assertEquals(6, DB::collection('items')->count('amount.*.hidden'));
        $this->assertEquals(1, DB::collection('items')->min('amount.*.hidden'));
        $this->assertEquals(35, DB::collection('items')->max('amount.*.hidden'));
        $this->assertEquals(12, DB::collection('items')->avg('amount.*.hidden'));
    }

Jens Segers's avatar
Jens Segers committed
493 494 495
    public function testUpsert()
    {
        DB::collection('items')->where('name', 'knife')
Jens Segers's avatar
Jens Segers committed
496 497 498 499
            ->update(
                ['amount' => 1],
                ['upsert' => true]
            );
Jens Segers's avatar
Jens Segers committed
500 501

        $this->assertEquals(1, DB::collection('items')->count());
502 503

        Item::where('name', 'spoon')
Jens Segers's avatar
Jens Segers committed
504
            ->update(
505 506 507 508 509
                ['amount' => 1],
                ['upsert' => true]
            );

        $this->assertEquals(2, DB::collection('items')->count());
Jens Segers's avatar
Jens Segers committed
510 511 512 513 514 515 516 517 518 519 520 521
    }

    public function testUnset()
    {
        $id1 = DB::collection('users')->insertGetId(['name' => 'John Doe', 'note1' => 'ABC', 'note2' => 'DEF']);
        $id2 = DB::collection('users')->insertGetId(['name' => 'Jane Doe', 'note1' => 'ABC', 'note2' => 'DEF']);

        DB::collection('users')->where('name', 'John Doe')->unset('note1');

        $user1 = DB::collection('users')->find($id1);
        $user2 = DB::collection('users')->find($id2);

Gabriel Caruso's avatar
Gabriel Caruso committed
522 523 524 525
        $this->assertArrayNotHasKey('note1', $user1);
        $this->assertArrayHasKey('note2', $user1);
        $this->assertArrayHasKey('note1', $user2);
        $this->assertArrayHasKey('note2', $user2);
Jens Segers's avatar
Jens Segers committed
526 527 528 529

        DB::collection('users')->where('name', 'Jane Doe')->unset(['note1', 'note2']);

        $user2 = DB::collection('users')->find($id2);
Gabriel Caruso's avatar
Gabriel Caruso committed
530 531
        $this->assertArrayNotHasKey('note1', $user2);
        $this->assertArrayNotHasKey('note2', $user2);
Jens Segers's avatar
Jens Segers committed
532 533 534 535 536 537 538 539 540 541 542 543 544 545 546
    }

    public function testUpdateSubdocument()
    {
        $id = DB::collection('users')->insertGetId(['name' => 'John Doe', 'address' => ['country' => 'Belgium']]);

        DB::collection('users')->where('_id', $id)->update(['address.country' => 'England']);

        $check = DB::collection('users')->find($id);
        $this->assertEquals('England', $check['address']['country']);
    }

    public function testDates()
    {
        DB::collection('users')->insert([
547 548 549 550
            ['name' => 'John Doe', 'birthday' => new UTCDateTime(1000 * strtotime("1980-01-01 00:00:00"))],
            ['name' => 'Jane Doe', 'birthday' => new UTCDateTime(1000 * strtotime("1981-01-01 00:00:00"))],
            ['name' => 'Robert Roe', 'birthday' => new UTCDateTime(1000 * strtotime("1982-01-01 00:00:00"))],
            ['name' => 'Mark Moe', 'birthday' => new UTCDateTime(1000 * strtotime("1983-01-01 00:00:00"))],
Jens Segers's avatar
Jens Segers committed
551 552
        ]);

Jens Segers's avatar
Jens Segers committed
553 554 555
        $user = DB::collection('users')
            ->where('birthday', new UTCDateTime(1000 * strtotime("1980-01-01 00:00:00")))
            ->first();
Jens Segers's avatar
Jens Segers committed
556 557 558 559 560
        $this->assertEquals('John Doe', $user['name']);

        $user = DB::collection('users')->where('birthday', '=', new DateTime("1980-01-01 00:00:00"))->first();
        $this->assertEquals('John Doe', $user['name']);

561 562
        $start = new UTCDateTime(1000 * strtotime("1981-01-01 00:00:00"));
        $stop = new UTCDateTime(1000 * strtotime("1982-01-01 00:00:00"));
Jens Segers's avatar
Jens Segers committed
563 564

        $users = DB::collection('users')->whereBetween('birthday', [$start, $stop])->get();
Gabriel Caruso's avatar
Gabriel Caruso committed
565
        $this->assertCount(2, $users);
Jens Segers's avatar
Jens Segers committed
566 567 568 569 570 571 572 573 574 575 576
    }

    public function testOperators()
    {
        DB::collection('users')->insert([
            ['name' => 'John Doe', 'age' => 30],
            ['name' => 'Jane Doe'],
            ['name' => 'Robert Roe', 'age' => 'thirty-one'],
        ]);

        $results = DB::collection('users')->where('age', 'exists', true)->get();
Gabriel Caruso's avatar
Gabriel Caruso committed
577
        $this->assertCount(2, $results);
Jens Segers's avatar
Jens Segers committed
578 579 580 581 582
        $resultsNames = [$results[0]['name'], $results[1]['name']];
        $this->assertContains('John Doe', $resultsNames);
        $this->assertContains('Robert Roe', $resultsNames);

        $results = DB::collection('users')->where('age', 'exists', false)->get();
Gabriel Caruso's avatar
Gabriel Caruso committed
583
        $this->assertCount(1, $results);
Jens Segers's avatar
Jens Segers committed
584 585 586
        $this->assertEquals('Jane Doe', $results[0]['name']);

        $results = DB::collection('users')->where('age', 'type', 2)->get();
Gabriel Caruso's avatar
Gabriel Caruso committed
587
        $this->assertCount(1, $results);
Jens Segers's avatar
Jens Segers committed
588 589 590
        $this->assertEquals('Robert Roe', $results[0]['name']);

        $results = DB::collection('users')->where('age', 'mod', [15, 0])->get();
Gabriel Caruso's avatar
Gabriel Caruso committed
591
        $this->assertCount(1, $results);
Jens Segers's avatar
Jens Segers committed
592 593 594
        $this->assertEquals('John Doe', $results[0]['name']);

        $results = DB::collection('users')->where('age', 'mod', [29, 1])->get();
Gabriel Caruso's avatar
Gabriel Caruso committed
595
        $this->assertCount(1, $results);
Jens Segers's avatar
Jens Segers committed
596 597 598
        $this->assertEquals('John Doe', $results[0]['name']);

        $results = DB::collection('users')->where('age', 'mod', [14, 0])->get();
Gabriel Caruso's avatar
Gabriel Caruso committed
599
        $this->assertCount(0, $results);
Jens Segers's avatar
Jens Segers committed
600 601

        DB::collection('items')->insert([
Jens Segers's avatar
Jens Segers committed
602
            ['name' => 'fork', 'tags' => ['sharp', 'pointy']],
Jens Segers's avatar
Jens Segers committed
603 604 605 606 607
            ['name' => 'spork', 'tags' => ['sharp', 'pointy', 'round', 'bowl']],
            ['name' => 'spoon', 'tags' => ['round', 'bowl']],
        ]);

        $results = DB::collection('items')->where('tags', 'all', ['sharp', 'pointy'])->get();
Gabriel Caruso's avatar
Gabriel Caruso committed
608
        $this->assertCount(2, $results);
Jens Segers's avatar
Jens Segers committed
609 610

        $results = DB::collection('items')->where('tags', 'all', ['sharp', 'round'])->get();
Gabriel Caruso's avatar
Gabriel Caruso committed
611
        $this->assertCount(1, $results);
Jens Segers's avatar
Jens Segers committed
612 613

        $results = DB::collection('items')->where('tags', 'size', 2)->get();
Gabriel Caruso's avatar
Gabriel Caruso committed
614
        $this->assertCount(2, $results);
Jens Segers's avatar
Jens Segers committed
615 616

        $results = DB::collection('items')->where('tags', '$size', 2)->get();
Gabriel Caruso's avatar
Gabriel Caruso committed
617
        $this->assertCount(2, $results);
Jens Segers's avatar
Jens Segers committed
618 619

        $results = DB::collection('items')->where('tags', 'size', 3)->get();
Gabriel Caruso's avatar
Gabriel Caruso committed
620
        $this->assertCount(0, $results);
Jens Segers's avatar
Jens Segers committed
621 622

        $results = DB::collection('items')->where('tags', 'size', 4)->get();
Gabriel Caruso's avatar
Gabriel Caruso committed
623
        $this->assertCount(1, $results);
Jens Segers's avatar
Jens Segers committed
624

625
        $regex = new Regex(".*doe", "i");
Jens Segers's avatar
Jens Segers committed
626
        $results = DB::collection('users')->where('name', 'regex', $regex)->get();
Gabriel Caruso's avatar
Gabriel Caruso committed
627
        $this->assertCount(2, $results);
Jens Segers's avatar
Jens Segers committed
628

629
        $regex = new Regex(".*doe", "i");
Jens Segers's avatar
Jens Segers committed
630
        $results = DB::collection('users')->where('name', 'regexp', $regex)->get();
Gabriel Caruso's avatar
Gabriel Caruso committed
631
        $this->assertCount(2, $results);
Jens Segers's avatar
Jens Segers committed
632 633

        $results = DB::collection('users')->where('name', 'REGEX', $regex)->get();
Gabriel Caruso's avatar
Gabriel Caruso committed
634
        $this->assertCount(2, $results);
Jens Segers's avatar
Jens Segers committed
635 636

        $results = DB::collection('users')->where('name', 'regexp', '/.*doe/i')->get();
Gabriel Caruso's avatar
Gabriel Caruso committed
637
        $this->assertCount(2, $results);
Jens Segers's avatar
Jens Segers committed
638 639

        $results = DB::collection('users')->where('name', 'not regexp', '/.*doe/i')->get();
Gabriel Caruso's avatar
Gabriel Caruso committed
640
        $this->assertCount(1, $results);
Jens Segers's avatar
Jens Segers committed
641 642 643

        DB::collection('users')->insert([
            [
Jens Segers's avatar
Jens Segers committed
644
                'name' => 'John Doe',
Jens Segers's avatar
Jens Segers committed
645 646 647 648 649 650
                'addresses' => [
                    ['city' => 'Ghent'],
                    ['city' => 'Paris'],
                ],
            ],
            [
Jens Segers's avatar
Jens Segers committed
651
                'name' => 'Jane Doe',
Jens Segers's avatar
Jens Segers committed
652 653 654 655 656 657 658 659
                'addresses' => [
                    ['city' => 'Brussels'],
                    ['city' => 'Paris'],
                ],
            ],
        ]);

        $users = DB::collection('users')->where('addresses', 'elemMatch', ['city' => 'Brussels'])->get();
Gabriel Caruso's avatar
Gabriel Caruso committed
660
        $this->assertCount(1, $users);
Jens Segers's avatar
Jens Segers committed
661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707
        $this->assertEquals('Jane Doe', $users[0]['name']);
    }

    public function testIncrement()
    {
        DB::collection('users')->insert([
            ['name' => 'John Doe', 'age' => 30, 'note' => 'adult'],
            ['name' => 'Jane Doe', 'age' => 10, 'note' => 'minor'],
            ['name' => 'Robert Roe', 'age' => null],
            ['name' => 'Mark Moe'],
        ]);

        $user = DB::collection('users')->where('name', 'John Doe')->first();
        $this->assertEquals(30, $user['age']);

        DB::collection('users')->where('name', 'John Doe')->increment('age');
        $user = DB::collection('users')->where('name', 'John Doe')->first();
        $this->assertEquals(31, $user['age']);

        DB::collection('users')->where('name', 'John Doe')->decrement('age');
        $user = DB::collection('users')->where('name', 'John Doe')->first();
        $this->assertEquals(30, $user['age']);

        DB::collection('users')->where('name', 'John Doe')->increment('age', 5);
        $user = DB::collection('users')->where('name', 'John Doe')->first();
        $this->assertEquals(35, $user['age']);

        DB::collection('users')->where('name', 'John Doe')->decrement('age', 5);
        $user = DB::collection('users')->where('name', 'John Doe')->first();
        $this->assertEquals(30, $user['age']);

        DB::collection('users')->where('name', 'Jane Doe')->increment('age', 10, ['note' => 'adult']);
        $user = DB::collection('users')->where('name', 'Jane Doe')->first();
        $this->assertEquals(20, $user['age']);
        $this->assertEquals('adult', $user['note']);

        DB::collection('users')->where('name', 'John Doe')->decrement('age', 20, ['note' => 'minor']);
        $user = DB::collection('users')->where('name', 'John Doe')->first();
        $this->assertEquals(10, $user['age']);
        $this->assertEquals('minor', $user['note']);

        DB::collection('users')->increment('age');
        $user = DB::collection('users')->where('name', 'John Doe')->first();
        $this->assertEquals(11, $user['age']);
        $user = DB::collection('users')->where('name', 'Jane Doe')->first();
        $this->assertEquals(21, $user['age']);
        $user = DB::collection('users')->where('name', 'Robert Roe')->first();
Gabriel Caruso's avatar
Gabriel Caruso committed
708
        $this->assertNull($user['age']);
Jens Segers's avatar
Jens Segers committed
709 710 711 712 713 714 715
        $user = DB::collection('users')->where('name', 'Mark Moe')->first();
        $this->assertEquals(1, $user['age']);
    }

    public function testProjections()
    {
        DB::collection('items')->insert([
Jens Segers's avatar
Jens Segers committed
716
            ['name' => 'fork', 'tags' => ['sharp', 'pointy']],
Jens Segers's avatar
Jens Segers committed
717 718 719 720 721 722
            ['name' => 'spork', 'tags' => ['sharp', 'pointy', 'round', 'bowl']],
            ['name' => 'spoon', 'tags' => ['round', 'bowl']],
        ]);

        $results = DB::collection('items')->project(['tags' => ['$slice' => 1]])->get();

Jens Segers's avatar
Jens Segers committed
723
        foreach ($results as $result) {
Jens Segers's avatar
Jens Segers committed
724 725 726
            $this->assertEquals(1, count($result['tags']));
        }
    }
727 728 729 730

    public function testValue()
    {
        DB::collection('books')->insert([
Jens Segers's avatar
Jens Segers committed
731
            ['title' => 'Moby-Dick', 'author' => ['first_name' => 'Herman', 'last_name' => 'Melville']],
732 733 734
        ]);

        $this->assertEquals('Moby-Dick', DB::collection('books')->value('title'));
Jens Segers's avatar
Jens Segers committed
735 736
        $this->assertEquals(['first_name' => 'Herman', 'last_name' => 'Melville'], DB::collection('books')
            ->value('author'));
737 738 739
        $this->assertEquals('Herman', DB::collection('books')->value('author.first_name'));
        $this->assertEquals('Melville', DB::collection('books')->value('author.last_name'));
    }
740
}