Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Mongodb Laravel Package

wangzd/mongodb

A MongoDB integration package for Laravel and PHP, offering database connectivity, query building, and model support so applications can use MongoDB alongside familiar Laravel conventions.

View on GitHub
Deep Wiki
Context7

Getting Started

This package is a fork of jenssegers/laravel-mongodb (the "Moloquent" lineage): it swaps Eloquent's SQL grammar for a MongoDB query/collection builder, so you get models, casts, relations, and Schema helpers backed by mongodb/mongodb.

Before you write a line of code, do three checks in this order — forks frequently diverge here:

  1. Open composer.json and note the require block. Which PHP driver does it expect — the modern ext-mongodb (with mongodb/mongodb) or the legacy ext-mongo? If it pins the legacy one, it will not run on PHP 7+, and you should stop here.
  2. Open src/ and read the namespace on the service provider and Model class. Forks of this repo usually keep Jenssegers\Mongodb\..., but verify — you need the exact FQCN for the provider and for every use statement.
  3. Check the illuminate/* version constraints. A zero-star fork is almost certainly pinned to an older Laravel major.

Then install and wire it up:

composer require wangzd/mongodb

Register the provider (if the package predates auto-discovery) in config/app.php:

'providers' => [
    Jenssegers\Mongodb\MongodbServiceProvider::class, // confirm against src/
],

Add a connection in config/database.php:

'mongodb' => [
    'driver'   => 'mongodb',
    'host'     => env('MONGO_HOST', '127.0.0.1'),
    'port'     => env('MONGO_PORT', 27017),
    'database' => env('MONGO_DATABASE'),
    'username' => env('MONGO_USERNAME'),
    'password' => env('MONGO_PASSWORD'),
    'options'  => [
        'database' => env('MONGO_AUTH_DB', 'admin'), // authSource
    ],
],

First use case — a flexible-schema collection that would be painful as SQL columns (catalog items, CMS blocks, event payloads):

use Jenssegers\Mongodb\Eloquent\Model; // verify namespace

class Product extends Model
{
    protected $connection = 'mongodb';
    protected $collection = 'products';
    protected $fillable   = ['sku', 'name', 'price', 'attributes'];
    protected $dates      = ['released_at'];
}

Product::create(['sku' => 'A-1', 'name' => 'Widget', 'attributes' => ['color' => 'red']]);
Product::where('attributes.color', 'red')->where('price', '<', 50)->get();

Where to look first: src/Eloquent/Model.php, src/Query/Builder.php, src/Collection.php, and src/Schema/Builder.php. Those four files tell you exactly which operators and schema helpers this fork actually supports — do not trust the parent project's README for the details.

Implementation Patterns

One model per collection, connection declared explicitly. Never rely on the default connection being Mongo; set protected $connection = 'mongodb' on every model so relational models continue to work untouched.

Embed what you read together, reference what you query independently. This is the single most important modeling decision and it drives everything else:

class Post extends Model
{
    public function comments() { return $this->embedsMany(Comment::class); }  // read with the post
    public function author()   { return $this->belongsTo(User::class); }       // queried on its own
}

Embdeds are stored inline, so Post::where('comments.author', 'taylor')->get() uses dot-notation and needs no join. Eager loading works: Post::with('comments', 'author')->paginate(20).

Use the query builder escape hatch for aggregation. Eloquent covers CRUD; reporting almost always needs the driver directly:

$totals = Order::raw(function ($collection) {
    return $collection->aggregate([
        ['$match'   => ['status' => 'paid']],
        ['$group'   => ['_id' => '$customer_id', 'total' => ['$sum' => '$amount']]],
        ['$sort'    => ['total' => -1]],
        ['$limit'   => 10],
    ]);
});

Reach for raw() rather than fighting groupBy/having translations — the grammar only covers a subset of SQL semantics.

Atomic field updates for counters and arrays. These bypass model hydration and are far cheaper than read-modify-save:

Product::where('sku', 'A-1')->increment('views');
Product::where('_id', $id)->push('tags', 'featured');
Product::where('_id', $id)->pull('tags', 'archived');
Product::where('_id', $id)->unset('legacy_field');

Manage indexes in migrations, not by hand. Treat them as schema:

Schema::connection('mongodb')->create('products', function ($collection) {
    $collection->index('sku', null, null, ['unique' => true]);
    $collection->index(['name' => 'text', 'description' => 'text']);
    $collection->index('attributes.color');
});

Ship this in a migration so every environment gets the same indexes; unindexed dot-notation queries are the usual cause of "Mongo is slow" complaints.

Hybrid persistence is the normal shape of a real app. Keep users/orders/payments in MySQL for referential integrity, and put the malleable stuff in Mongo. Cross-connection hasMany will not join — resolve it in PHP (User::find($id)->posts where posts is a Mongo model referencing user_id) or denormalize the fields you need onto the document.

Thin repository layer for aggregation-heavy reads. Wrap raw()/aggregate() calls in a repository so tests can stub them and so you have one place to add explain() and index hints.

Testing: use a dedicated database (app_test) and drop collections in setUp(). RefreshDatabase and DatabaseTransactions do not apply — there are no transactions to roll back.

Gotchas and Tips

  • _id is an ObjectId, not a string. Model::find($id) casts correctly; where('_id', $id) with a raw string may silently return nothing depending on the fork's version. When in doubt: ->where('_id', new \MongoDB\BSON\ObjectId($id)).
  • Set $incrementing = false and $keyType = 'string' on your base model. Auto-increment assumptions leak in through save() and relation resolution otherwise.
  • Nested change detection is unreliable. Mutating $model->attributes['color'] in place often won't mark the field dirty. Reassign the whole array or use ->push()/->pull() for atomic, guaranteed writes.
  • Query-builder updates skip model events and timestamps. Product::where(...)->update([...]) won't touch updated_at. Add '$currentDate' => ['updated_at' => true] or go through the model.
  • The unique validation rule has no database backstop unless you created a unique index. Register a custom validator that queries the collection, and create the index.
  • No joins, no foreign keys, no cascading deletes. Deleting a parent leaves orphaned _id references. Handle cleanup explicitly (an observer or a queued prune job).
  • paginate() runs a count() over the whole filter. Fine at 50k documents, painful at 5M. For big collections use range-based pagination on an indexed field (_id > $lastId) instead of skip/limit.
  • Regex searches can't use indexes efficiently. Prefer a text index with where('$text' => ['$search' => ...]), or denormalize a lowercase field and match exactly.
  • Auth failures are almost always authSource. Set options.database => 'admin' (or the user's database) when credentials live outside the app database.
  • Debugging: DB::connection('mongodb')->enableQueryLog() then getQueryLog(); ->explain() on any builder for index usage; ->toMongo() on a query to see the raw filter before it hits the server.
  • Cache the config (php artisan config:cache) after changing connection options — Laravel will happily keep using the stale cached array and confuse you for an hour.
  • Biggest risk: this package is effectively unmaintained — 0 stars, 0 dependents, a fork of a fork. Pin the exact version in composer.json, keep it behind a composer.json repositories vcs entry so you can patch it in place, and write your Mongo usage so it's portable: models, $fillable, and raw() calls are the same API in mongodb/laravel-mongodb. Budget a migration to the official driver before your next Laravel major upgrade; the fork will break on it.
  • Extension mismatch is the classic install failure. ext-mongodb (new) and ext-mongo (legacy, dead since PHP 7) are not interchangeable. If composer install or the provider's boot() blows up, check php -m | grep mongo first.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator
equipc/laravel-email-database-log
adedsec/nova-translated-labels
wazza/laravel-db-encryption
hokny/laravel-generator
vonsogt/backup
jengo/queues
jeremykenedy/laravel-observability
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums