herdianrony / mongolite
MongoDB-like interface with SQLite backend
Installs: 3
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/herdianrony/mongolite
Requires (Dev)
- phpunit/phpunit: ^9.0
This package is auto-updated.
Last update: 2025-12-28 08:48:27 UTC
README
High-performance MongoDB-compatible query engine with SQLite backend
MongoLite is a lightweight, production-ready library that provides MongoDB-style queries and aggregations using SQLite as the storage engine. Originally developed as part of Cockpit CMS, it has been extracted and enhanced as a standalone library.
๐ About
This library was originally part of the Cockpit CMS project. It has been extracted, improved, and is now maintained as a separate package for broader use in PHP applications that need a lightweight, file-based NoSQL solution.
โจ Features
๐ Query Engine
- 25+ Query Operators: Complete support for MongoDB query syntax
- Advanced Filtering:
$and,$or,$not,$nor,$where,$expr - Comparison Operators:
$eq,$ne,$gt,$gte,$lt,$lte - Array Operators:
$in,$nin,$all,$size,$elemMatch - Pattern Matching:
$regex,$textwith fuzzy search - Field Validation:
$exists,$type,$mod
๐ Aggregation Framework
- 18+ Pipeline Stages: Complete aggregation pipeline support
- 10 Accumulator Operators:
$sum,$avg,$min,$max,$first,$last,$push,$addToSet,$stdDevPop,$stdDevSamp - Data Transformation:
$project,$addFields,$unset,$unwind - Grouping & Sorting:
$group,$sort,$sortByCount,$bucket - Sampling & Analysis:
$sample,$facet,$count - Joins:
$lookupfor data relationships
๐ Geospatial Support
- Location Queries:
$near,$geoWithin,$geoIntersects - Geometric Shapes: Point, Polygon, Circle, Box support
- Distance Calculations: Haversine formula for accurate distances
- Aggregation Integration:
$geoNearpipeline stage
๐ค Output Stages
- Data Export:
$outstage for collection replacement - Data Merging:
$mergestage with conflict resolution - Flexible Options:
whenMatched,whenNotMatchedbehaviors
๐ Security & Performance
- SQL Injection Protection: Comprehensive input sanitization
- Memory Efficient: Optimized for large dataset processing
- Production Ready: Tested with 1000+ record datasets
- Error Resilient: Graceful handling of edge cases
๐ Quick Start
Basic Usage
<?php require_once 'MongoLite/Database.php'; use MongoLite\Database; // Create database $db = new Database('/path/to/database.db'); $collection = $db->selectCollection('users'); // Insert documents $collection->insert([ 'name' => 'John Doe', 'email' => 'john@example.com', 'age' => 30, 'location' => ['coordinates' => [-74.0059, 40.7128]] ]); // Query documents $users = $collection->find(['age' => ['$gte' => 25]])->toArray(); // Update documents $collection->update(['name' => 'John Doe'], ['$set' => ['age' => 31]]); // Delete documents $collection->remove(['age' => ['$lt' => 18]]);
Advanced Queries
// Complex filtering $results = $collection->find([ '$and' => [ ['age' => ['$gte' => 18]], ['$or' => [ ['status' => 'active'], ['premium' => true] ]] ] ])->toArray(); // Text search with fuzzy matching $searchResults = $collection->find([ 'description' => [ '$text' => [ '$search' => 'mongodb query', '$minScore' => 0.8 ] ] ])->toArray(); // Geospatial queries $nearbyUsers = $collection->find([ 'location' => [ '$geoWithin' => [ '$center' => [[-74.0059, 40.7128], 1000] // 1km radius ] ] ])->toArray();
Aggregation Pipeline
// Business intelligence aggregation $analytics = $collection->aggregate([ // Filter active users ['$match' => ['status' => 'active']], // Group by department ['$group' => [ '_id' => '$department', 'employee_count' => ['$sum' => 1], 'avg_salary' => ['$avg' => '$salary'], 'salary_std_dev' => ['$stdDevPop' => '$salary'], 'top_performer' => ['$first' => '$name'], 'all_employees' => ['$push' => '$name'] ]], // Sort by average salary ['$sort' => ['avg_salary' => -1]], // Add calculated fields ['$addFields' => [ 'salary_category' => [ '$cond' => [ 'if' => ['$gte' => ['$avg_salary', 75000]], 'then' => 'High', 'else' => 'Standard' ] ] ]], // Export results ['$out' => 'department_analytics'] ])->toArray();
Geospatial Operations
// Find stores near a location $nearbyStores = $collection->aggregate([ ['$geoNear' => [ 'near' => ['coordinates' => [-73.9857, 40.7484]], // Times Square 'distanceField' => 'distance_meters', 'maxDistance' => 5000, // 5km radius 'query' => ['type' => 'retail'] ]], ['$project' => [ 'name' => 1, 'address' => 1, 'distance_km' => ['$divide' => ['$distance_meters', 1000]] ]], ['$sort' => ['distance_meters' => 1]], ['$limit' => 10] ])->toArray(); // Point in polygon check $inBoundary = $collection->find([ 'delivery_zone' => [ '$geoIntersects' => [ '$geometry' => [ 'type' => 'Polygon', 'coordinates' => [[[0,0], [10,0], [10,10], [0,10], [0,0]]] ] ] ] ])->toArray();
๐ API Reference
Database Class
$db = new Database($path, $options = []); // Collection management $collection = $db->selectCollection($name); $db->createCollection($name); $db->dropCollection($name); $names = $db->getCollectionNames(); // Security $safeName = $db->sanitizeCollectionName($name); // Utility $db->vacuum(); // Optimize database $db->drop(); // Delete database
Collection Class
// CRUD Operations $result = $collection->insert($document); $count = $collection->insertMany($documents); $cursor = $collection->find($criteria, $projection); $document = $collection->findOne($criteria, $projection); $collection->update($criteria, $data, $options); $collection->remove($criteria, $options); // Aggregation $cursor = $collection->aggregate($pipeline); // Utility $count = $collection->count($criteria); $collection->drop();
Cursor Class
// Iteration foreach ($cursor as $document) { // Process document } // Conversion $array = $cursor->toArray(); // Pagination $cursor->skip($offset)->limit($count); $cursor->sort(['field' => 1]); // 1 = ASC, -1 = DESC
๐๏ธ Architecture
Core Components
MongoLite/
โโโ Database.php # Database connection and management
โโโ Collection.php # Collection operations and CRUD
โโโ Cursor.php # Query result iteration
โโโ UtilArrayQuery.php # Query engine and operators
โโโ Projection.php # Field projection logic
โโโ Aggregation/
โโโ Cursor.php # Aggregation pipeline processor
โโโ ValueAccessor.php # Nested field manipulation
Storage Layer
- Backend: SQLite with JSON document storage
- Schema: Dynamic document structure in BLOB fields
- Indexing: Automatic SQLite indexing for performance
- ACID: Full transaction support via SQLite
Query Processing
- Parse: MongoDB query โ Internal AST
- Validate: Security checks and sanitization
- Transform: AST โ SQLite query + Filters
- Execute: SQLite query with post-processing
- Return: MongoDB-compatible results
๐ง Advanced Configuration
Database Options
$options = [ PDO::ATTR_TIMEOUT => 30, PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC ]; $db = new Database('/path/to/db.sqlite', $options);
Memory Database
// In-memory database for testing $db = new Database(':memory:');
Custom Functions
// Register custom SQLite functions $db->connection->sqliteCreateFunction('custom_func', function($value) { return strtoupper($value); });
๐ Performance Guidelines
Optimization Tips
-
Use Projections: Limit returned fields
$collection->find($criteria, ['name' => 1, 'email' => 1]);
-
Efficient Filtering: Place most selective criteria first
['status' => 'active', 'age' => ['$gte' => 18]] // status first if more selective
-
Limit Results: Use pagination for large datasets
$collection->find($criteria)->skip(0)->limit(50);
-
Aggregation Optimization: Filter early in pipeline
[ ['$match' => $criteria], // Filter first ['$group' => $grouping], // Then group ['$sort' => $sorting] // Finally sort ]
Memory Management
// Process large datasets in chunks $offset = 0; $limit = 1000; while (true) { $batch = $collection->find($criteria) ->skip($offset) ->limit($limit) ->toArray(); if (empty($batch)) break; // Process batch foreach ($batch as $document) { // Handle document } $offset += $limit; }
๐ Security Best Practices
Input Validation
// โ Good: Use sanitization $safeName = $db->sanitizeCollectionName($userInput); if ($safeName === null) { throw new InvalidArgumentException('Invalid collection name'); } // โ Good: Validate field names $allowedFields = ['name', 'email', 'age']; $projection = array_intersect_key($userProjection, array_flip($allowedFields));
Query Safety
// โ Good: Use MongoDB operators $criteria = [ 'email' => ['$regex' => preg_quote($searchTerm)] ]; // โ Avoid: String interpolation in queries // $criteria = ['email' => '/' . $searchTerm . '/i']; // Potentially unsafe
๐งช Testing
Unit Tests
<?php use MongoLite\Database; // Test setup $db = new Database(':memory:'); $collection = $db->selectCollection('test'); // Test insert $doc = ['name' => 'Test', 'value' => 123]; $collection->insert($doc); // Test query $result = $collection->findOne(['name' => 'Test']); assert($result['value'] === 123); // Test aggregation $stats = $collection->aggregate([ ['$group' => [ '_id' => null, 'total' => ['$sum' => '$value'] ]] ])->toArray(); assert($stats[0]['total'] === 123);
Performance Testing
// Benchmark aggregation performance $start = microtime(true); $results = $collection->aggregate([ ['$match' => ['status' => 'active']], ['$group' => ['_id' => '$category', 'count' => ['$sum' => 1]]], ['$sort' => ['count' => -1]] ])->toArray(); $elapsed = microtime(true) - $start; echo "Aggregation took: " . round($elapsed, 3) . "s\n";
๐ค MongoDB Compatibility
Supported Operations
| Feature | MongoDB | MongoLite | Notes |
|---|---|---|---|
| Query Operators | โ | โ | 25+ operators |
| Aggregation Pipeline | โ | โ | 18+ stages |
| Geospatial Queries | โ | โ | Point, Polygon support |
| Text Search | โ | โ | Fuzzy matching |
| Transactions | โ | โ | Via SQLite ACID |
| Sharding | โ | โ | Single database file |
| Replica Sets | โ | โ | SQLite limitation |
Migration from MongoDB
// MongoDB syntax works directly $results = $collection->find([ 'age' => ['$gte' => 21], 'status' => ['$in' => ['active', 'pending']] ])->toArray(); // Aggregation pipelines are identical $analytics = $collection->aggregate([ ['$match' => ['type' => 'user']], ['$group' => [ '_id' => '$department', 'count' => ['$sum' => 1], 'avgAge' => ['$avg' => '$age'] ]] ])->toArray();
๐ง Troubleshooting
Common Issues
Q: "Call to undefined function"
// Ensure all required files are included require_once 'MongoLite/Database.php'; require_once 'MongoLite/Collection.php'; require_once 'MongoLite/UtilArrayQuery.php';
Q: "Permission denied" on database file
# Fix file permissions
chmod 644 /path/to/database.db
chmod 755 /path/to/database/directory
Q: "Invalid collection name" error
// Use sanitization for user input $safeName = $db->sanitizeCollectionName($userInput); if ($safeName) { $collection = $db->selectCollection($safeName); }
Q: Poor aggregation performance
// Optimize pipeline order $pipeline = [ ['$match' => $criteria], // Filter first ['$group' => $grouping], // Then group ['$sort' => $sorting], // Sort last ['$limit' => 100] // Limit results ];
Debug Mode
// Enable SQLite logging for debugging $db->connection->sqliteCreateFunction('debug_log', function($message) { error_log("MongoLite Debug: $message"); return $message; });
๐ License
MIT License - see LICENSE file for details.
๐ Credits
- Original development team at Cockpit CMS
- Current maintainers: [Your Name/Organization]
- Contributors: [List of contributors if any]
Ready to get started? Check out the Quick Start guide above!
๐ Related Projects
- Cockpit CMS - The original project where MongoLite was developed
- MongoLite - This standalone version