mongodb/laravel-mongodb
MongoDB integration for Laravel Eloquent and query builder. Extends core Laravel classes to use the same familiar API with MongoDB. Official mongodb/laravel-mongodb package, compatible with Laravel 10.x; docs and releases maintained by MongoDB.
## Getting Started
### Minimal Setup
1. **Installation**:
```bash
composer require mongodb/laravel-mongodb
Add to config/app.php under providers:
MongoDB\Laravel\MongoDBServiceProvider::class,
Configuration: Publish the config file:
php artisan vendor:publish --provider="MongoDB\Laravel\MongoDBServiceProvider"
Update .env with your MongoDB connection string:
MONGODB_CONNECTION=default
MONGODB_DATABASE=your_database
MONGODB_URI=mongodb://username:password@host:port/database
First Model:
Extend MongoDB\Laravel\Eloquent\Model instead of Illuminate\Database\Eloquent\Model:
use MongoDB\Laravel\Eloquent\Model;
class User extends Model
{
protected $connection = 'default';
protected $collection = 'users';
protected $fillable = ['name', 'email'];
}
First Query:
$users = User::where('name', 'John')->get();
$user = User::find('507f1f77bcf86cd799439011');
create(), update(), delete()) as usual.$result = User::aggregate([
['$match' => ['age' => ['$gt' => 25]]],
['$group' => ['_id' => '$department', 'count' => ['$sum' => 1]]]
]);
schema() method:
public static function schema()
{
return [
'bsonType' => 'object',
'properties' => [
'name' => ['bsonType' => 'string'],
'email' => ['bsonType' => 'string', 'pattern' => '^.+@.+\\..+$']
],
'required' => ['name', 'email']
];
}
protected $collection to define the MongoDB collection name.$ref or embed directly:
class Address extends Model
{
protected $collection = 'addresses';
}
class User extends Model
{
public function address()
{
return $this->embedOne('address');
}
}
up() method of migrations:
Schema::create('users', function (Blueprint $collection) {
$collection->index('email', ['unique' => true]);
$collection->index(['name', 'created_at']);
});
$query = User::query()
->where('name', 'John')
->where('age', '>', 30)
->orderBy('created_at', 'desc')
->limit(10);
aggregate() for complex operations:
$pipeline = [
['$match' => ['status' => 'active']],
['$lookup' => [
'from' => 'orders',
'localField' => '_id',
'foreignField' => 'user_id',
'as' => 'orders'
]]
];
$result = User::aggregate($pipeline);
$text operator:
$users = User::where('name', ['$text' => ['$search' => 'John']])->get();
DB::transaction():
DB::transaction(function () {
User::create(['name' => 'Alice']);
Order::create(['user_id' => $user->id, 'amount' => 100]);
});
DB::transaction(function () use (&$retries) {
try {
// Transaction logic
} catch (MongoDB\Driver\Exception\RuntimeException $e) {
if ($retries++ < 3) {
return $this->transaction($callback);
}
throw $e;
}
});
class User extends Model
{
public function addresses()
{
return $this->embedMany('address');
}
}
class User extends Model
{
public function orders()
{
return $this->hasMany(Order::class);
}
}
class Comment extends Model
{
public function commentable()
{
return $this->morphTo();
}
}
observables() in boot():
protected static function boot()
{
parent::boot();
static::observables(['created', 'updated']);
}
class UserObserver
{
public function creating(User $user)
{
$user->uuid = Str::uuid()->toString();
}
}
Register in AppServiceProvider:
User::observe(UserObserver::class);
Schema facade:
Schema::create('users', function (Blueprint $collection) {
$collection->index('email', ['unique' => true, 'sparse' => true]);
$collection->index('created_at', ['expireAfterSeconds' => 2592000]); // TTL index
});
Schema::createView('user_view', ['viewOn' => 'users'], function (Blueprint $view) {
$view->viewDefinition([
['$match' => ['status' => 'active']],
['$project' => ['name' => 1, 'email' => 1]]
]);
});
class User extends Model
{
public function shouldBeSearchable()
{
return $this->isActive();
}
public function toSearchableArray()
{
return ['name' => $this->name, 'email' => $this->email];
}
}
Configure in config/scout.php:
'driver' => 'mongodb',
ID Handling:
_id (ObjectId) by default, not auto-incrementing integers.Str::uuid() or ObjectId for custom IDs:
use MongoDB\BSON\ObjectId;
$id = new ObjectId();
$primaryKey, ensure it’s castable to/from BSON:
protected $primaryKey = 'uuid';
protected $keyType = 'string';
Soft Deletes:
MongoSoftDeletes trait in favor of native MongoDB isDeleted field.use MongoDB\Laravel\Eloquent\SoftDeletes;
class User extends Model
{
use SoftDeletes;
protected $dates = ['deleted_at'];
}
withTrashed() to include them:
User::withTrashed()->get();
Schema Validation:
save() and update(). Invalid data throws MongoDB\Driver\Exception\InvalidArgumentException.prepareForValidation() to catch issues early:
protected function prepareForValidation()
{
if (empty($this->email)) {
throw new \InvalidArgumentException('Email is required.');
}
}
Aggregation Quirks:
$match early to reduce documents processed.$allowDiskUse:How can I help you explore Laravel packages today?