QueryBuilderTest.php 27.5 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
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    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([
548 549 550 551
            ['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
552 553
        ]);

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

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

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

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

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

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

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

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

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

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

        $results = DB::collection('items')->where('tags', 'size', 2)->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', '$size', 2)->get();
Gabriel Caruso's avatar
Gabriel Caruso committed
618
        $this->assertCount(2, $results);
Jens Segers's avatar
Jens Segers committed
619 620

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

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

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

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

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

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

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

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

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

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

    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
752 753 754
        $this->assertEquals('spoon', $results[0]['name']);
        $this->assertEquals('spork', $results[1]['name']);
        $this->assertEquals('fork', $results[2]['name']);
755 756 757

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

Ditty's avatar
Ditty committed
758 759 760
        $this->assertEquals('spoon', $results[2]['name']);
        $this->assertEquals('spork', $results[1]['name']);
        $this->assertEquals('fork', $results[0]['name']);
761
    }
762
}