README.md 16.5 KB
Newer Older
Jens Segers's avatar
Jens Segers committed
1
Laravel MongoDB
Jens Segers's avatar
Jens Segers committed
2
===============
Jens Segers's avatar
Jens Segers committed
3

Jens Segers's avatar
Jens Segers committed
4
[![Latest Stable Version](http://img.shields.io/github/release/jenssegers/laravel-mongodb.svg)](https://packagist.org/packages/jenssegers/mongodb) [![Total Downloads](http://img.shields.io/packagist/dm/jenssegers/mongodb.svg)](https://packagist.org/packages/jenssegers/mongodb) [![Build Status](http://img.shields.io/travis/jenssegers/laravel-mongodb.svg)](https://travis-ci.org/jenssegers/laravel-mongodb) [![Coverage Status](http://img.shields.io/coveralls/jenssegers/laravel-mongodb.svg)](https://coveralls.io/r/jenssegers/laravel-mongodb?branch=master)
Jens Segers's avatar
Jens Segers committed
5

Jens Segers's avatar
Jens Segers committed
6
An Eloquent model and Query builder with support for MongoDB, inspired by LMongo, but using the original Laravel methods. *This library extends the original Laravel classes, so it uses exactly the same methods.*
Jens Segers's avatar
Jens Segers committed
7

8 9 10
Installation
------------

Jens Segers's avatar
Jens Segers committed
11
Add the package to your `composer.json` and run `composer update`.
12

Jens Segers's avatar
Jens Segers committed
13 14 15 16
    {
        "require": {
            "jenssegers/mongodb": "*"
        }
17 18
    }

Jens Segers's avatar
Jens Segers committed
19
Add the service provider in `app/config/app.php`:
20

Jens Segers's avatar
Jens Segers committed
21
    'Jenssegers\Mongodb\MongodbServiceProvider',
Jens Segers's avatar
Jens Segers committed
22

Jens Segers's avatar
Jens Segers committed
23
The service provider will register a mongodb database extension with the original database manager. There is no need to register additional facades or objects. When using mongodb connections, Laravel will automatically provide you with the corresponding mongodb objects.
Jens Segers's avatar
Jens Segers committed
24 25 26 27

Configuration
-------------

28 29 30 31 32
Change your default database connection name in `app/config/database.php`:

    'default' => 'mongodb',

And add a new mongodb connection:
Jens Segers's avatar
Jens Segers committed
33

Jens Segers's avatar
Jens Segers committed
34
    'mongodb' => array(
35
        'driver'   => 'mongodb',
Jens Segers's avatar
Jens Segers committed
36 37
        'host'     => 'localhost',
        'port'     => 27017,
38 39 40
        'username' => 'username',
        'password' => 'password',
        'database' => 'database'
Jens Segers's avatar
Jens Segers committed
41
    ),
Jens Segers's avatar
Jens Segers committed
42

43 44 45
You can connect to multiple servers or replica sets with the following configuration:

    'mongodb' => array(
46
        'driver'   => 'mongodb',
47
        'host'     => array('server1', 'server2'),
48 49 50 51 52 53 54
        'port'     => 27017,
        'username' => 'username',
        'password' => 'password',
        'database' => 'database',
        'options'  => array('replicaSet' => 'replicaSetName')
    ),

55
Eloquent
56 57
--------

Jens Segers's avatar
Jens Segers committed
58 59
Tell your model to use the MongoDB model and set the collection (alias for table) property. The lower-case, plural name of the class will be used for the collection name, unless another name is explicitly specified.

Jens Segers's avatar
Jens Segers committed
60
    use Jenssegers\Mongodb\Model as Eloquent;
Jens Segers's avatar
Jens Segers committed
61

62
    class MyModel extends Eloquent {
Jens Segers's avatar
Jens Segers committed
63

64
        protected $collection = 'mycollection';
Jens Segers's avatar
Jens Segers committed
65

66 67
    }

Jens Segers's avatar
Jens Segers committed
68 69 70 71 72 73 74 75 76
If you are using a different database driver as the default one, you will need to specify the mongodb connection within your model by changing the `connection` property:

    use Jenssegers\Mongodb\Model as Eloquent;

    class MyModel extends Eloquent {

        protected $connection = 'mongodb';

    }
77

Jens Segers's avatar
Jens Segers committed
78
Everything else works just like the original Eloquent model. Read more about the Eloquent on http://laravel.com/docs/eloquent
79

Jens Segers's avatar
Jens Segers committed
80 81 82 83 84 85 86
### Optional: Alias

You may also register an alias for the MongoDB model by adding the following to the alias array in `app/config/app.php`:

    'Moloquent'       => 'Jenssegers\Mongodb\Model',

This will allow you to use your registered alias like:
wikichua's avatar
wikichua committed
87 88 89 90 91 92 93

    class MyModel extends Moloquent {

        protected $collection = 'mycollection';

    }

94 95 96
Query Builder
-------------

97
The database driver plugs right into the original query builder. When using mongodb connections you will be able to build fluent queries to perform database operations. For your convenience, there is a `collection` alias for `table` as well as some additional mongodb specific operators/operations.
Jens Segers's avatar
Jens Segers committed
98

Jens Segers's avatar
Jens Segers committed
99 100
    // With custom connection
    $user = DB::connection('mongodb')->collection('users')->get();
101

Jens Segers's avatar
Jens Segers committed
102
    // Using default connection
103 104
    $users = DB::collection('users')->get();
    $user = DB::collection('users')->where('name', 'John')->first();
105

Jens Segers's avatar
Jens Segers committed
106 107
Read more about the query builder on http://laravel.com/docs/queries

108 109 110 111 112
Schema
------

The database driver also has (limited) schema builder support. You can easily manipulate collections and set indexes:

Jens Segers's avatar
Jens Segers committed
113
    Schema::create('users', function($collection)
114 115 116 117 118 119 120
    {
        $collection->index('name');
        $collection->unique('email');
    });

Supported operations are:

Jens Segers's avatar
Jens Segers committed
121 122 123
 - create and drop
 - collection
 - hasCollection
124
 - index and dropIndex (compound indexes supported as well)
125 126
 - unique
 - background, sparse, expire (MongoDB specific)
127 128 129

Read more about the schema builder on http://laravel.com/docs/schema

130 131 132 133 134 135 136 137 138
Auth
----

If you want to use Laravel's native Auth functionality, register this included service provider:

    'Jenssegers\Mongodb\Auth\ReminderServiceProvider',

This service provider will slightly modify the internal DatabaseReminderRepository to add support for MongoDB based password reminders. If you don't use password reminders, you don't have to register this service provider and everything else should work just fine.

139 140 141 142 143
Sentry
------

If yo want to use this library with [Sentry](https://cartalyst.com/manual/sentry), then check out https://github.com/jenssegers/Laravel-MongoDB-Sentry

Jens Segers's avatar
Jens Segers committed
144 145 146
Sessions
--------

147
The MongoDB session driver is available in a separate package, check out https://github.com/jenssegers/Laravel-MongoDB-Session
Jens Segers's avatar
Jens Segers committed
148

Jens Segers's avatar
Jens Segers committed
149 150
Examples
--------
151

Jens Segers's avatar
Jens Segers committed
152 153
### Basic Usage

154 155
**Retrieving All Models**

Jens Segers's avatar
Jens Segers committed
156
    $users = User::all();
157 158 159

**Retrieving A Record By Primary Key**

Jens Segers's avatar
Jens Segers committed
160
    $user = User::find('517c43667db388101e00000f');
161 162 163

**Wheres**

Jens Segers's avatar
Jens Segers committed
164
    $users = User::where('votes', '>', 100)->take(10)->get();
165 166 167

**Or Statements**

Jens Segers's avatar
Jens Segers committed
168
    $users = User::where('votes', '>', 100)->orWhere('name', 'John')->get();
169 170 171

**Using Where In With An Array**

Jens Segers's avatar
Jens Segers committed
172
    $users = User::whereIn('age', array(16, 18, 20))->get();
Jens Segers's avatar
Jens Segers committed
173

Jens Segers's avatar
Jens Segers committed
174
When using `whereNotIn` objects will be returned if the field is non existent. Combine with `whereNotNull('age')` to leave out those documents.
175

Jens Segers's avatar
Jens Segers committed
176 177
**Using Where Between**

Jens Segers's avatar
Jens Segers committed
178
    $users = User::whereBetween('votes', array(1, 100))->get();
Jens Segers's avatar
Jens Segers committed
179

Jens Segers's avatar
Jens Segers committed
180 181
**Where null**

Jens Segers's avatar
Jens Segers committed
182
    $users = User::whereNull('updated_at')->get();
183 184 185

**Order By**

Jens Segers's avatar
Jens Segers committed
186
    $users = User::orderBy('name', 'desc')->get();
187

Jens Segers's avatar
Jens Segers committed
188 189
**Offset & Limit**

Jens Segers's avatar
Jens Segers committed
190
    $users = User::skip(10)->take(5)->get();
Jens Segers's avatar
Jens Segers committed
191

Jens Segers's avatar
Jens Segers committed
192 193 194 195
**Distinct**

Distinct requires a field for which to return the distinct values.

Jens Segers's avatar
Jens Segers committed
196 197 198
    $users = User::distinct()->get(array('name'));
    // or
    $users = User::distinct('name')->get();
Jens Segers's avatar
Jens Segers committed
199

Jens Segers's avatar
Jens Segers committed
200 201
Distinct can be combined with **where**:

Jens Segers's avatar
Jens Segers committed
202
    $users = User::where('active', true)->distinct('name')->get();
Jens Segers's avatar
Jens Segers committed
203

204 205
**Advanced Wheres**

Jens Segers's avatar
Jens Segers committed
206
    $users = User::where('name', '=', 'John')->orWhere(function($query)
Jens Segers's avatar
Jens Segers committed
207 208 209 210 211
        {
            $query->where('votes', '>', 100)
                  ->where('title', '<>', 'Admin');
        })
        ->get();
212

Jens Segers's avatar
Jens Segers committed
213 214
**Group By**

Jens Segers's avatar
Jens Segers committed
215 216
Selected columns that are not grouped will be aggregated with the $last function.

Jens Segers's avatar
Jens Segers committed
217
    $users = Users::groupBy('title')->get(array('title', 'name'));
Jens Segers's avatar
Jens Segers committed
218 219

**Aggregation**
Jens Segers's avatar
Jens Segers committed
220

221 222
*Aggregations are only available for MongoDB versions greater than 2.2.*

Jens Segers's avatar
Jens Segers committed
223 224 225 226 227
    $total = Order::count();
    $price = Order::max('price');
    $price = Order::min('price');
    $price = Order::avg('price');
    $total = Order::sum('price');
Jens Segers's avatar
Jens Segers committed
228 229 230

Aggregations can be combined with **where**:

Jens Segers's avatar
Jens Segers committed
231
    $sold = Orders::where('sold', true)->sum('price');
Jens Segers's avatar
Jens Segers committed
232 233 234

**Like**

Jens Segers's avatar
Jens Segers committed
235
    $user = Comment::where('body', 'like', '%spam%')->get();
Jens Segers's avatar
Jens Segers committed
236

237
**Incrementing or decrementing a value of a column**
238

239
Perform increments or decrements (default 1) on specified attributes:
240

Jens Segers's avatar
Jens Segers committed
241 242
    User::where('name', 'John Doe')->increment('age');
    User::where('name', 'Jaques')->decrement('weight', 50);
243

244
The number of updated objects is returned:
245

Jens Segers's avatar
Jens Segers committed
246
    $count = User->increment('age');
247

248
You may also specify additional columns to update:
249

Jens Segers's avatar
Jens Segers committed
250 251
    User::where('age', '29')->increment('age', 1, array('group' => 'thirty something'));
    User::where('bmi', 30)->decrement('bmi', 1, array('category' => 'overweight'));
Jens Segers's avatar
Jens Segers committed
252

253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268
**Soft deleting**

When soft deleting a model, it is not actually removed from your database. Instead, a deleted_at timestamp is set on the record. To enable soft deletes for a model, apply the SoftDeletingTrait to the model:

use Jenssegers\Mongodb\Eloquent\SoftDeletingTrait;

class User extends Eloquent {

    use SoftDeletingTrait;

    protected $dates = ['deleted_at'];

}

For more information check http://laravel.com/docs/eloquent#soft-deleting

269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288
### MongoDB specific operators

**Exists**

Matches documents that have the specified field.

    User::where('age', 'exists', true)->get();

**All**

Matches arrays that contain all elements specified in the query.

    User::where('roles', 'all', array('moderator', 'author'))->get();

**Size**

Selects documents if the array field is a specified size.

    User::where('tags', 'size', 3)->get();

Jens Segers's avatar
Jens Segers committed
289 290 291 292 293 294
**Regex**

Selects documents where values match a specified regular expression.

    User::where('name', 'regex', new MongoRegex("/.*doe/i"))->get();

295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310
**Type**

Selects documents if a field is of the specified type. For more information check: http://docs.mongodb.org/manual/reference/operator/query/type/#op._S_type

    User::where('age', 'type', 2)->get();

**Mod**

Performs a modulo operation on the value of a field and selects documents with a specified result.

    User::where('age', 'mod', array(10, 0))->get();

**Where**

Matches documents that satisfy a JavaScript expression. For more information check http://docs.mongodb.org/manual/reference/operator/query/where/#op._S_where

Jens Segers's avatar
Jens Segers committed
311 312 313 314
### Inserts, updates and deletes

All basic insert, update, delete and select methods should be implemented.

315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332
### Dates

Eloquent allows you to work with Carbon/DateTime objects instead of MongoDate objects. Internally, these dates will be converted to MongoDate objects when saved to the database. If you wish to use this functionality on non-default date fields you will need to manually specify them as described here: http://laravel.com/docs/eloquent#date-mutators

Example:

    use Jenssegers\Mongodb\Model as Eloquent;

    class User extends Eloquent {

        protected $dates = array('birthday');

    }

Which allows you to execute queries like:

    $users = User::where('birthday', '>', new DateTime('-18 years'))->get();

Jens Segers's avatar
Jens Segers committed
333
### Relations
Jens Segers's avatar
Jens Segers committed
334

Jens Segers's avatar
Jens Segers committed
335
Supported relations are:
Jens Segers's avatar
Jens Segers committed
336 337 338 339

 - hasOne
 - hasMany
 - belongsTo
340 341
 - belongsToMany

Jens Segers's avatar
Jens Segers committed
342 343
Example:

Jens Segers's avatar
Jens Segers committed
344 345
    use Jenssegers\Mongodb\Model as Eloquent;

Jens Segers's avatar
Jens Segers committed
346 347 348 349 350 351 352 353 354 355 356
    class User extends Eloquent {

        public function items()
        {
            return $this->hasMany('Item');
        }

    }

And the inverse relation:

Jens Segers's avatar
Jens Segers committed
357 358
    use Jenssegers\Mongodb\Model as Eloquent;

Jens Segers's avatar
Jens Segers committed
359 360 361 362 363 364 365 366 367
    class Item extends Eloquent {

        public function user()
        {
            return $this->belongsTo('User');
        }

    }

Jens Segers's avatar
Jens Segers committed
368 369 370 371 372 373 374 375 376 377 378 379 380
The belongsToMany relation will not use a pivot "table", but will push id's to a __related_ids__ attribute instead. This makes the second parameter for the belongsToMany method useless. If you want to define custom keys for your relation, set it to `null`:

    use Jenssegers\Mongodb\Model as Eloquent;

    class User extends Eloquent {

        public function groups()
        {
            return $this->belongsToMany('Group', null, 'users', 'groups');
        }

    }

Jens Segers's avatar
Jens Segers committed
381 382
Other relations are not yet supported, but may be added in the future. Read more about these relations on http://four.laravel.com/docs/eloquent#relationships

383 384 385 386 387 388 389 390 391 392 393 394 395 396 397
### EmbedsMany Relations

If you want to embed documents, rather than referencing them, you can use the `embedsMany` relation:

    use Jenssegers\Mongodb\Model as Eloquent;

    class User extends Eloquent {

        public function books()
        {
            return $this->embedsMany('Book');
        }

    }

Jens Segers's avatar
Jens Segers committed
398
Now we can access the user's books through the dynamic property:
399 400 401

    $books = User::first()->books;

Jens Segers's avatar
Jens Segers committed
402 403 404 405
When using embedded documents, there will also be an inverse relation available:

    $user = $book->user;

406 407 408 409 410 411 412 413 414 415 416 417 418
Inserting and updating embedded documents works just like the `belongsTo` relation:

    $book = new Book(array('title' => 'A Game of Thrones'));

    $user = User::first();

    $book = $user->books()->save($book);

You can remove an embedded document by using the `destroy()` method:

    $book = $user->books()->first();

    $user->books()->destroy($book->_id);
Jens Segers's avatar
Jens Segers committed
419 420
    // or
    $user->books()->destroy($book);
421

422 423 424 425 426
If you want to add or remove embedded documents, without persistence, you can use the `associate` and `dissociate` methods. To write the changes to the database, save the parent object:

    $user->books()->associate($book);
    $user->save();

427 428 429 430
Again, you may override the conventional local key by passing a second argument to the embedsMany method:

    return $this->embedsMany('Book', 'local_key');

431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457
### EmbedsOne Relations

There is also an EmbedsOne relation, which works similar to the EmbedsMany relation, but only stores one embedded model.

    use Jenssegers\Mongodb\Model as Eloquent;

    class Book extends Eloquent {

        public function author()
        {
            return $this->embedsOne('Author');
        }

    }

Now we can access the book's author through the dynamic property:

    $author = Book::first()->author;

Inserting and updating embedded documents works just like the `embedsMany` relation:

    $author = new Author(array('name' => 'John Doe'));

    $book = Books::first();

    $author = $user->author()->save($author);

458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491
### MySQL Relations

If you're using a hybrid MongoDB and SQL setup, you're in luck! The model will automatically return a MongoDB- or SQL-relation based on the type of the related model. Of course, if you want this functionality to work both ways, your SQL-models will need to extend `Jenssegers\Eloquent\Model`. Note that this functionality only works for hasOne, hasMany and belongsTo relations.

Example SQL-based User model:

    use Jenssegers\Eloquent\Model as Eloquent;

    class User extends Eloquent {

        protected $connection = 'mysql';

        public function messages()
        {
            return $this->hasMany('Message');
        }

    }

And the Mongodb-based Message model:

    use Jenssegers\Mongodb\Model as Eloquent;

    class Message extends Eloquent {

        protected $connection = 'mongodb';

        public function user()
        {
            return $this->belongsTo('User');
        }

    }

Jens Segers's avatar
Jens Segers committed
492
### Raw Expressions
Jens Segers's avatar
Jens Segers committed
493 494 495 496 497

These expressions will be injected directly into the query.

    User::whereRaw(array('age' => array('$gt' => 30, '$lt' => 40)))->get();

498
You can also perform raw expressions on the internal MongoCollection object. If this is executed on the model class, it will return a collection of models. If this is executed on the query builder, it will return the original response.
499

500 501
    // Returns a collection of User models.
    $models = User::raw(function($collection)
502 503 504 505
    {
        return $collection->find();
    });

506 507
    // Returns the original MongoCursor.
    $cursor = DB::collection('users')->raw(function($collection)
508 509 510 511
    {
        return $collection->find();
    });

512
Optional: if you don't pass a closure to the raw method, the internal MongoCollection object will be accessible:
513

514
    $model = User::raw()->findOne(array('age' => array('$lt' => 18)));
515

516 517 518 519 520
The MongoClient and MongoDB objects can be accessed like this:

    $client = DB::getMongoClient();
    $db = DB::getMongoDB();

521 522
### MongoDB specific operations

Jens Segers's avatar
Jens Segers committed
523 524 525 526 527 528 529
**Upsert**

Update or insert a document. Additional options for the update method are passed directly to the native update method.

    DB::collection('users')->where('name', 'John')
                           ->update($data, array('upsert' => true));

Jens Segers's avatar
Jens Segers committed
530
**Push**
531

532
Add an items to an array.
533

Jens Segers's avatar
Jens Segers committed
534
    DB::collection('users')->where('name', 'John')->push('items', 'boots');
535
    DB::collection('users')->where('name', 'John')->push('messages', array('from' => 'Jane Doe', 'message' => 'Hi John'));
536

537 538 539 540
If you don't want duplicate items, set the third parameter to `true`:

    DB::collection('users')->where('name', 'John')->push('items', 'boots', true);

Jens Segers's avatar
Jens Segers committed
541
**Pull**
Jens Segers's avatar
Jens Segers committed
542

543
Remove an item from an array.
Jens Segers's avatar
Jens Segers committed
544

Jens Segers's avatar
Jens Segers committed
545
    DB::collection('users')->where('name', 'John')->pull('items', 'boots');
546
    DB::collection('users')->where('name', 'John')->pull('messages', array('from' => 'Jane Doe', 'message' => 'Hi John'));
Jens Segers's avatar
Jens Segers committed
547

Jens Segers's avatar
Jens Segers committed
548 549 550 551 552 553 554 555 556 557 558
**Unset**

Remove one or more fields from a document.

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

You can also perform an unset on a model.

    $user = User::where('name', 'John')->first();
    $user->unset('note');

Jens Segers's avatar
Jens Segers committed
559
### Query Caching
Jens Segers's avatar
Jens Segers committed
560 561 562

You may easily cache the results of a query using the remember method:

Jens Segers's avatar
Jens Segers committed
563
    $users = User::remember(10)->get();
564

Jens Segers's avatar
Jens Segers committed
565 566
*From: http://laravel.com/docs/queries#caching-queries*

567 568 569 570 571
### Query Logging

By default, Laravel keeps a log in memory of all queries that have been run for the current request. However, in some cases, such as when inserting a large number of rows, this can cause the application to use excess memory. To disable the log, you may use the `disableQueryLog` method:

    DB::connection()->disableQueryLog();
Jens Segers's avatar
Jens Segers committed
572 573

*From: http://laravel.com/docs/database#query-logging*