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

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

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

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 49 50
    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);

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

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

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

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

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

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

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

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

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

    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
92
        $this->assertCount(1, $users);
Jens Segers's avatar
Jens Segers committed
93 94 95

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

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

    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
119
        $this->assertCount(2, $users);
120
        $this->assertIsArray($users[0]['tags']);
Jens Segers's avatar
Jens Segers committed
121 122 123 124 125 126 127 128 129 130 131 132 133
    }

    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
134
        $this->assertNull($user);
Jens Segers's avatar
Jens Segers committed
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
    }

    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]);

        $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']);
Ditty's avatar
Ditty committed
179 180
        $result = DB::collection('users')->truncate();
        $this->assertEquals(1, $result);
Jens Segers's avatar
Jens Segers committed
181 182 183 184 185 186 187
        $this->assertEquals(0, DB::collection('users')->count());
    }

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

        $users = DB::collection('users')->where('address.country', 'Belgium')->get();
Gabriel Caruso's avatar
Gabriel Caruso committed
198
        $this->assertCount(1, $users);
Jens Segers's avatar
Jens Segers committed
199 200 201 202 203 204 205 206 207 208 209 210 211 212 213
        $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
214
        $this->assertCount(2, $items);
Jens Segers's avatar
Jens Segers committed
215 216

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

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

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

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

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

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

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

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

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

        $user = DB::collection('users')->find($id);
256
        $this->assertIsArray($user['tags']);
Gabriel Caruso's avatar
Gabriel Caruso committed
257
        $this->assertCount(1, $user['tags']);
Jens Segers's avatar
Jens Segers committed
258 259 260 261
        $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
262
        $this->assertCount(2, $user['tags']);
Jens Segers's avatar
Jens Segers committed
263 264 265 266 267
        $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
268
        $this->assertCount(3, $user['tags']);
Jens Segers's avatar
Jens Segers committed
269 270 271 272

        // 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
273
        $this->assertCount(3, $user['tags']);
Jens Segers's avatar
Jens Segers committed
274 275 276 277

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

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

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

    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
307 308
            'name' => 'John Doe',
            'tags' => ['tag1', 'tag2', 'tag3', 'tag4'],
Jens Segers's avatar
Jens Segers committed
309 310 311 312 313 314
            'messages' => [$message1, $message2],
        ]);

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

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

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

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

        // 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
328 329
        $this->assertCount(2, $user['tags']);
        $this->assertCount(0, $user['messages']);
Jens Segers's avatar
Jens Segers committed
330 331 332 333 334 335
    }

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

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

Pooya Parsa's avatar
Pooya Parsa committed
346
        $types = DB::collection('items')->distinct('type')->get()->toArray();
Jens Segers's avatar
Jens Segers committed
347
        sort($types);
Gabriel Caruso's avatar
Gabriel Caruso committed
348
        $this->assertCount(2, $types);
Jens Segers's avatar
Jens Segers committed
349 350 351 352 353 354 355
        $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
356
            ['_id' => 'fork', 'type' => 'sharp', 'amount' => 20],
Jens Segers's avatar
Jens Segers committed
357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378
            ['_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
379
            ['name' => 'fork', 'type' => 'sharp', 'amount' => 20],
Jens Segers's avatar
Jens Segers committed
380 381 382 383 384
            ['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
385
        $this->assertCount(2, $items);
Jens Segers's avatar
Jens Segers committed
386 387 388 389 390 391 392
        $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
393
            ['name' => 'fork', 'type' => 'sharp', 'amount' => 20],
Jens Segers's avatar
Jens Segers committed
394 395 396 397 398
            ['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
399
        $this->assertCount(2, $items);
Jens Segers's avatar
Jens Segers committed
400 401 402 403 404 405 406 407 408 409
        $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
410
        $age = DB::collection('users')->where('name', 'John Doe')->pluck('age')->toArray();
411
        $this->assertEquals([25], $age);
Jens Segers's avatar
Jens Segers committed
412 413 414 415 416 417
    }

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

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

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

Pooya Parsa's avatar
Pooya Parsa committed
432
        $list = DB::collection('items')->pluck('name', '_id')->toArray();
Gabriel Caruso's avatar
Gabriel Caruso committed
433
        $this->assertCount(4, $list);
Jens Segers's avatar
Jens Segers committed
434 435 436 437 438 439 440
        $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
441
            ['name' => 'fork', 'type' => 'sharp', 'amount' => 20],
Jens Segers's avatar
Jens Segers committed
442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459
            ['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
460
            ['name' => 'fork', 'amount' => ['hidden' => 35, 'found' => 12]],
Jens Segers's avatar
Jens Segers committed
461 462 463 464 465 466 467 468 469 470 471
            ['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'));
    }

472 473 474
    public function testSubdocumentArrayAggregate()
    {
        DB::collection('items')->insert([
475
            ['name' => 'knife', 'amount' => [['hidden' => 10, 'found' => 3], ['hidden' => 5, 'found' => 2]]],
Jens Segers's avatar
Jens Segers committed
476 477 478 479 480 481 482 483
            [
                'name' => 'fork',
                'amount' => [
                    ['hidden' => 35, 'found' => 12],
                    ['hidden' => 7, 'found' => 17],
                    ['hidden' => 1, 'found' => 19],
                ],
            ],
484 485 486 487 488 489 490 491 492 493 494
            ['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
495 496 497
    public function testUpsert()
    {
        DB::collection('items')->where('name', 'knife')
Jens Segers's avatar
Jens Segers committed
498 499 500 501
            ->update(
                ['amount' => 1],
                ['upsert' => true]
            );
Jens Segers's avatar
Jens Segers committed
502 503

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

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

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

    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
524 525 526 527
        $this->assertArrayNotHasKey('note1', $user1);
        $this->assertArrayHasKey('note2', $user1);
        $this->assertArrayHasKey('note1', $user2);
        $this->assertArrayHasKey('note2', $user2);
Jens Segers's avatar
Jens Segers committed
528 529 530 531

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

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

    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([
549 550 551 552
            ['name' => 'John Doe', 'birthday' => new UTCDateTime(Date::parse("1980-01-01 00:00:00")->format('Uv'))],
            ['name' => 'Jane Doe', 'birthday' => new UTCDateTime(Date::parse("1981-01-01 00:00:00")->format('Uv'))],
            ['name' => 'Robert Roe', 'birthday' => new UTCDateTime(Date::parse("1982-01-01 00:00:00")->format('Uv'))],
            ['name' => 'Mark Moe', 'birthday' => new UTCDateTime(Date::parse("1983-01-01 00:00:00")->format('Uv'))],
Jens Segers's avatar
Jens Segers committed
553 554
        ]);

Jens Segers's avatar
Jens Segers committed
555
        $user = DB::collection('users')
556
            ->where('birthday', new UTCDateTime(Date::parse("1980-01-01 00:00:00")->format('Uv')))
Jens Segers's avatar
Jens Segers committed
557
            ->first();
Jens Segers's avatar
Jens Segers committed
558 559 560 561 562
        $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']);

563 564
        $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
565 566

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

    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
579
        $this->assertCount(2, $results);
Jens Segers's avatar
Jens Segers committed
580 581 582 583 584
        $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
585
        $this->assertCount(1, $results);
Jens Segers's avatar
Jens Segers committed
586 587 588
        $this->assertEquals('Jane Doe', $results[0]['name']);

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

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

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

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

        DB::collection('items')->insert([
Jens Segers's avatar
Jens Segers committed
604
            ['name' => 'fork', 'tags' => ['sharp', 'pointy']],
Jens Segers's avatar
Jens Segers committed
605 606 607 608 609
            ['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
610
        $this->assertCount(2, $results);
Jens Segers's avatar
Jens Segers committed
611 612

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

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

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

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

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

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

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

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

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

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

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

        $users = DB::collection('users')->where('addresses', 'elemMatch', ['city' => 'Brussels'])->get();
Gabriel Caruso's avatar
Gabriel Caruso committed
662
        $this->assertCount(1, $users);
Jens Segers's avatar
Jens Segers committed
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 708 709
        $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
710
        $this->assertNull($user['age']);
Jens Segers's avatar
Jens Segers committed
711 712 713 714 715 716 717
        $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
718
            ['name' => 'fork', 'tags' => ['sharp', 'pointy']],
Jens Segers's avatar
Jens Segers committed
719 720 721 722 723 724
            ['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
725
        foreach ($results as $result) {
Jens Segers's avatar
Jens Segers committed
726 727 728
            $this->assertEquals(1, count($result['tags']));
        }
    }
729 730 731 732

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

        $this->assertEquals('Moby-Dick', DB::collection('books')->value('title'));
Jens Segers's avatar
Jens Segers committed
737 738
        $this->assertEquals(['first_name' => 'Herman', 'last_name' => 'Melville'], DB::collection('books')
            ->value('author'));
739 740 741
        $this->assertEquals('Herman', DB::collection('books')->value('author.first_name'));
        $this->assertEquals('Melville', DB::collection('books')->value('author.last_name'));
    }
742 743 744 745 746 747 748 749 750 751 752

    public function testHintOptions()
    {
        DB::collection('items')->insert([
            ['name' => 'fork',  'tags' => ['sharp', 'pointy']],
            ['name' => 'spork', 'tags' => ['sharp', 'pointy', 'round', 'bowl']],
            ['name' => 'spoon', 'tags' => ['round', 'bowl']],
        ]);

        $results = DB::collection('items')->hint(['$natural' => -1])->get();

Ditty's avatar
Ditty committed
753 754 755
        $this->assertEquals('spoon', $results[0]['name']);
        $this->assertEquals('spork', $results[1]['name']);
        $this->assertEquals('fork', $results[2]['name']);
756 757 758

        $results = DB::collection('items')->hint(['$natural' => 1])->get();

Ditty's avatar
Ditty committed
759 760 761
        $this->assertEquals('spoon', $results[2]['name']);
        $this->assertEquals('spork', $results[1]['name']);
        $this->assertEquals('fork', $results[0]['name']);
762
    }
fso's avatar
fso committed
763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781

    public function testCursor()
    {
        $data = [
            ['name' => 'fork', 'tags' => ['sharp', 'pointy']],
            ['name' => 'spork', 'tags' => ['sharp', 'pointy', 'round', 'bowl']],
            ['name' => 'spoon', 'tags' => ['round', 'bowl']],
        ];
        DB::collection('items')->insert($data);

        $results = DB::collection('items')->orderBy('_id', 'asc')->cursor();

        $this->assertInstanceOf(LazyCollection::class, $results);
        $i = 0;
        foreach ($results as $result) {
            $this->assertEquals($data[$i]['name'], $result['name']);
            $i++;
        }
    }
782
}