amoradb
v1.1.0
Published
A lightweight, file-based NoSQL database for Node.js applications with MongoDB-like query syntax and zero dependencies for core functionality.
Readme
AmoraDB
A lightweight, file-based NoSQL database for Node.js applications with MongoDB-like query syntax and zero dependencies for core functionality.
🎯 Why AmoraDB?
AmoraDB bridges the gap between simple JSON file storage and complex database systems. Perfect for:
- Rapid Prototyping: Start building immediately without database setup
- Small to Medium Applications: Handle thousands of records efficiently
- Electron/Desktop Apps: Embedded database with no external dependencies
- Microservices: Lightweight data persistence without infrastructure overhead
- Educational Projects: Learn database concepts with readable JSON storage
- Offline-First Applications: Full functionality without network connectivity
✨ Key Features
- 🚀 Zero Configuration: No server setup, no connection strings
- 📁 Human-Readable Storage: Data stored as formatted JSON files
- 🔍 MongoDB-like Queries: Familiar syntax with operators like
$gte,$regex,$in - ⚡ Indexed Queries: Create indices for lightning-fast lookups
- 🔗 Chainable API: Build complex queries with intuitive method chaining
- 💾 ACID-like Guarantees: Atomic writes with transaction support
- 🎯 In-Memory Caching: LRU cache for optimal performance
- 📊 Aggregation Pipeline: Built-in sum, average, min, max operations
- 🔄 Real-time Events: EventEmitter for reactive applications
- 🛡️ Type Safety: Full TypeScript support (coming soon)
📦 Installation
npm install amoradbOr with yarn:
yarn add amoradb🚀 Quick Start
const AmoraDB = require('amoradb');
// Initialize database
const db = new AmoraDB('myapp');
await db.init();
// Get a table (collection)
const users = db.table('users');
// Insert data
const user = users.insert({
name: 'Sarah Connor',
email: '[email protected]',
age: 29,
role: 'leader'
});
// Query with operators
const results = await users
.find({ age: { $gte: 18 } })
.sort('name', 'asc')
.limit(10)
.execute();
// Update records
await users.update(user._id, { status: 'active' });
// Close when done
await db.close();📖 Core Concepts
Database Structure
data/
└── myapp/ # Database directory
├── _metadata.json # Database metadata
├── users.jsonl # Users table
├── orders.jsonl # Orders table
└── products.jsonl # Products tableTables (Collections)
Tables are schema-less document stores that hold related data. Each table is stored as a separate JSON file.
const users = db.table('users'); // Get or create table
const products = db.table('products');Documents
Documents are JavaScript objects with automatic metadata:
{
_id: "uuid-here", // Auto-generated unique ID
_created: "2024-01-01T00:00:00Z", // Creation timestamp
_modified: "2024-01-01T00:00:00Z", // Last modified timestamp
...yourData // Your custom fields
}🔍 Query Language
Basic Queries
// Find all
users.all().execute();
// Find with conditions
users.find({ status: 'active' }).execute();
// Find one
await users.findOne({ email: '[email protected]' });
// Find by ID
await users.findById('uuid-here');Query Operators
| Operator | Description | Example |
|----------|-------------|---------|
| $eq | Equals | { age: { $eq: 25 } } |
| $ne | Not equals | { status: { $ne: 'deleted' } } |
| $gt | Greater than | { age: { $gt: 18 } } |
| $gte | Greater than or equal | { score: { $gte: 90 } } |
| $lt | Less than | { price: { $lt: 100 } } |
| $lte | Less than or equal | { quantity: { $lte: 5 } } |
| $in | In array | { role: { $in: ['admin', 'mod'] } } |
| $nin | Not in array | { status: { $nin: ['banned', 'deleted'] } } |
| $regex | Pattern match | { email: { $regex: '@gmail.com' } } |
| $exists | Field exists | { phone: { $exists: true } } |
Complex Queries
// Chained conditions
const premiumUsers = await users
.find({ age: { $gte: 18 } })
.and({ subscription: 'premium' })
.or({ role: 'vip' })
.sort('joinDate', 'desc')
.skip(0)
.limit(20)
.execute();
// Select specific fields
const emails = await users
.find({ newsletter: true })
.select(['email', 'name'])
.execute();
// Distinct values
const uniqueCities = users.all().distinct('address.city');📊 Aggregation
const stats = await users
.find({ active: true })
.aggregate({
totalUsers: { $count: true },
totalAge: { $sum: 'age' },
avgAge: { $avg: 'age' },
minAge: { $min: 'age' },
maxAge: { $max: 'age' }
});
console.log(stats);
// { totalUsers: 150, totalAge: 4500, avgAge: 30, minAge: 18, maxAge: 65 }⚡ Performance Optimization
Indexing
Create indices for frequently queried fields:
users.createIndex('email'); // Fast email lookups
users.createIndex('username'); // Fast username queries
users.createIndex('created_at'); // Fast date sortingCaching
Built-in LRU cache with configurable size:
const db = new AmoraDB('myapp', {
cacheSize: 5000 // Cache up to 5000 records in memory
});
// Monitor cache performance
const stats = users.cache.getStats();
console.log(`Cache hit rate: ${stats.hitRate * 100}%`);🔄 Real-time Events
users.on('insert', (record) => {
console.log('New user:', record);
});
users.on('update', (record) => {
console.log('Updated user:', record);
});
users.on('delete', (record) => {
console.log('Deleted user:', record);
});🛠️ API Reference
Database Methods
| Method | Description |
|--------|-------------|
| new AmoraDB(name, options) | Create database instance |
| await db.init() | Initialize database |
| db.table(name) | Get or create table |
| await db.dropTable(name) | Delete table |
| await db.listTables() | List all tables |
| await db.backup(path) | Backup database |
| await db.close() | Close database |
Table Methods
| Method | Description |
|--------|-------------|
| insert(record) | Insert single record |
| insertMany(records) | Insert multiple records |
| find(query) | Query builder |
| findOne(query) | Find first match |
| findById(id) | Find by ID |
| update(id, changes) | Update by ID |
| updateMany(query, changes) | Update multiple |
| delete(id) | Delete by ID |
| deleteMany(query) | Delete multiple |
| count(query) | Count matching records |
| createIndex(field) | Create index |
| all() | Get all records |
Query Methods
| Method | Description |
|--------|-------------|
| where(condition) | Add condition |
| and(condition) | AND condition |
| or(condition) | OR condition |
| sort(field, order) | Sort results |
| limit(n) | Limit results |
| skip(n) | Skip records |
| select(fields) | Select fields |
| distinct(field) | Unique values |
| aggregate(ops) | Aggregation |
| execute() | Run query |
🎯 Use Cases
1. User Management System
const users = db.table('users');
users.createIndex('email');
// Registration
const newUser = users.insert({
email: '[email protected]',
password: hashedPassword,
profile: {
name: 'John Doe',
avatar: 'avatar.jpg'
}
});
// Authentication
const user = users.findOne({
email: '[email protected]',
active: true
});
// Update last login
users.update(user._id, {
lastLogin: new Date().toISOString()
});2. Shopping Cart
const carts = db.table('carts');
// Add to cart
carts.insert({
userId: 'user-123',
items: [
{ productId: 'prod-1', quantity: 2, price: 29.99 },
{ productId: 'prod-2', quantity: 1, price: 49.99 }
],
total: 109.97
});
// Get user's cart
const cart = carts.findOne({ userId: 'user-123' });
// Calculate totals
const stats = carts.aggregate({
totalRevenue: { $sum: 'total' },
avgCartValue: { $avg: 'total' },
cartCount: { $count: true }
});3. Activity Logger
const logs = db.table('activity_logs');
logs.createIndex('timestamp');
logs.createIndex('userId');
// Log activity
logs.insert({
userId: 'user-123',
action: 'LOGIN',
timestamp: Date.now(),
metadata: { ip: '192.168.1.1', device: 'mobile' }
});
// Query recent activities
const recentLogs = await logs
.find({
timestamp: { $gte: Date.now() - 86400000 } // Last 24h
})
.sort('timestamp', 'desc')
.limit(100)
.execute();⚙️ Configuration Options
const db = new AmoraDB('myapp', {
dataPath: './custom/path', // Custom data directory
cacheSize: 2000, // LRU cache size
autoSave: true, // Auto-save on changes
compression: false, // Compression (future feature)
indexAutoCreate: true // Auto-create indices
});🚀 Performance Benchmarks
=== PERFORMANCE BENCHMARK RESULTS ===
| Operation | Records | Time (ms) | Ops/sec | Memory (MB) | |-----------|---------|-----------|---------|-------------| | Single Insert (1,000 records) | 1,000 | 16 | 62,663 | 3.84 | | Batch Insert (100,000 records) | 100,000 | 1,672 | 59,801 | 378.46 | | Simple Indexed Query (category) | 10,001 | 4 | 2,360,443 | 1.68 | | Complex Indexed Query (price range) | 10,057 | 11 | 900,926 | 8.93 | | Non-indexed Query (name pattern) | 11,111 | 36 | 312,514 | -2.88 | | Sorted Query with Limit (top 1000 by price) | 1,000 | 13 | 76,240 | -11.2 | | Aggregation (price statistics) | 1 | 22 | 45 | 6.68 | | Count Query (all active products) | 25,001 | 2 | 11,957,429 | 3.36 | | Distinct Query (unique categories) | 10 | 27 | 371 | -2.41 | | Single Updates (10,000 records) | 10,000 | 1,387 | 7,208 | 2.02 | | Batch Update (50,000 records) | 10,001 | 1,222 | 8,185 | 3.71 | | Single Deletes (5,000 records) | 5,000 | 318 | 15,705 | -0.33 | | Batch Delete (remaining archived) | 20,000 | 1,044 | 19,159 | -0.86 | | Memory Efficient Insert (50,000 records, small cache) | 50,000 | 518 | 96,577 | -151.46 | | Streaming Query (large dataset) | 100 | 22 | 4,579 | 3.08 |
=== SUMMARY === Total Records Processed: 253,282 Total Time: 6.31s Average Performance: 40,114 ops/sec
Benchmarks on MacBook Pro M1, Node.js 18
🔒 Limitations
- File Size: Best for databases under 100MB
- Concurrency: Single-process only (no multi-process support)
- Transactions: Basic transaction support, not full ACID
- Scalability: Not suitable for high-traffic production systems
🗺️ Roadmap
- [ ] TypeScript definitions (In Progress)
- [x] Better Memory Optimization
- [ ] Bun Support
- [ ] Multi-process support with file locking
- [ ] Data compression
- [ ] Encrypted storage
- [ ] Browser support (IndexedDB backend)
- [ ] Replication and sync
- [ ] Query optimization engine
- [ ] Migrations system
- [ ] CLI tools
🤝 Contributing
Contributions are welcome! Please read our Contributing Guide for details.
# Clone repository
git clone https://github.com/samuelail/amoradb.git
# Install dependencies
npm install
# Run tests
npm test
# Build
npm run build📄 License
MIT © Samuel Ailemen
🙏 Acknowledgments
Inspired by:
Support
- 🐛 Issues: GitHub Issues
Built with ❤️ for developers
