QueryBuilderTest.php 28.4 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
            ['name' => 'John Doe', 'birthday' => new UTCDateTime(Date::parse("1980-01-01 00:00:00")->format('Uv'))],
            ['name' => 'Robert Roe', 'birthday' => new UTCDateTime(Date::parse("1982-01-01 00:00:00")->format('Uv'))],
551 552
            ['name' => 'Mark Moe', 'birthday' => new UTCDateTime(Date::parse("1983-01-01 00:00:00.1")->format('Uv'))],
            ['name' => 'Frank White', 'birthday' => new UTCDateTime(Date::parse("1960-01-01 12:12:12.1")->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
        $this->assertEquals('John Doe', $user['name']);

560 561 562 563 564
        $user = DB::collection('users')
            ->where('birthday', new UTCDateTime(Date::parse("1960-01-01 12:12:12.1")->format('Uv')))
            ->first();
        $this->assertEquals('Frank White', $user['name']);

Jens Segers's avatar
Jens Segers committed
565 566 567
        $user = DB::collection('users')->where('birthday', '=', new DateTime("1980-01-01 00:00:00"))->first();
        $this->assertEquals('John Doe', $user['name']);

568 569
        $start = new UTCDateTime(1000 * strtotime("1950-01-01 00:00:00"));
        $stop = new UTCDateTime(1000 * strtotime("1981-01-01 00:00:00"));
Jens Segers's avatar
Jens Segers committed
570 571

        $users = DB::collection('users')->whereBetween('birthday', [$start, $stop])->get();
Gabriel Caruso's avatar
Gabriel Caruso committed
572
        $this->assertCount(2, $users);
Jens Segers's avatar
Jens Segers committed
573 574 575 576 577 578 579 580 581 582 583
    }

    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
584
        $this->assertCount(2, $results);
Jens Segers's avatar
Jens Segers committed
585 586 587 588 589
        $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
590
        $this->assertCount(1, $results);
Jens Segers's avatar
Jens Segers committed
591 592 593
        $this->assertEquals('Jane Doe', $results[0]['name']);

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

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

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

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

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

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

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

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

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

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

632
        $regex = new Regex(".*doe", "i");
Jens Segers's avatar
Jens Segers committed
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
        $regex = new Regex(".*doe", "i");
Jens Segers's avatar
Jens Segers committed
637
        $results = DB::collection('users')->where('name', 'regexp', $regex)->get();
Gabriel Caruso's avatar
Gabriel Caruso committed
638
        $this->assertCount(2, $results);
Jens Segers's avatar
Jens Segers committed
639 640

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

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

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

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

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

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

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

    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
758 759 760
        $this->assertEquals('spoon', $results[0]['name']);
        $this->assertEquals('spork', $results[1]['name']);
        $this->assertEquals('fork', $results[2]['name']);
761 762 763

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

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

    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);
fso's avatar
fso committed
781
        foreach ($results as $i => $result) {
fso's avatar
fso committed
782 783 784
            $this->assertEquals($data[$i]['name'], $result['name']);
        }
    }
785
}