flongo
v1.2.0
Published
Firestore-like fluent query API for MongoDB
Maintainers
Readme
Flongo 🔥🍃
Firestore-like fluent query API for MongoDB
Flongo brings the intuitive, chainable query syntax of Firestore to MongoDB, making database operations more readable and developer-friendly.
Installation
npm install flongoQuick Start
import { initializeFlongo, FlongoCollection, FlongoQuery } from 'flongo';
// Initialize MongoDB connection
initializeFlongo({
connectionString: 'mongodb://localhost:27017',
dbName: 'myapp'
});
// Define your data interface
interface User {
name: string;
email: string;
age: number;
tags: string[];
}
// Create a collection
const users = new FlongoCollection<User>('users');
// Query with fluent API
const adults = await users.getAll(
new FlongoQuery()
.where('age').gtEq(18)
.and('tags').arrContainsAny(['developer', 'designer'])
.orderBy('name')
);Features
- 🔗 Chainable queries - Firestore-like fluent API
- 🚀 TypeScript support - Full type safety and IntelliSense
- 📊 Rich query operations - Comparisons, arrays, geospatial, text search
- 🎛️ Configurable - Optional event logging, custom error handling
- 🧪 Battle-tested - Extracted from production codebase
- 📦 Zero config - Works with existing MongoDB setup
API Reference
Basic Queries
const query = new FlongoQuery();
// Equality
query.where('status').eq('active')
// Comparisons
query.where('age').gt(21).and('age').lt(65)
query.where('score').gtEq(80).and('score').ltEq(100)
query.where('status').neq('deleted')
// Arrays
query.where('tags').arrContains('featured')
query.where('categories').arrContainsAny(['tech', 'design'])
query.where('skills').arrContainsAll(['js', 'react'])
query.where('id').in(['user1', 'user2', 'user3'])
query.where('role').notIn(['admin', 'banned'])
// Text search
query.where('name').startsWith('John')
query.where('email').endsWith('@gmail.com')
query.where('bio').strContains('developer')
// Ranges
query.inRange('price', 100, 500)Advanced Queries
// OR queries
const activeOrFeatured = new FlongoQuery()
.where('status').eq('active')
.or(
new FlongoQuery().where('featured').eq(true)
);
// Geospatial queries
query.where('location').geoWithin({
ne: { latitude: 40.7829, longitude: -73.9441 },
sw: { latitude: 40.7489, longitude: -73.9441 }
});
// Radius search
query.inRadius('location', { latitude: 40.7589, longitude: -73.9851 }, 1000);
// Sorting and pagination
const results = await collection.getAll(
query.orderBy('createdAt', SortDirection.Descending),
{ offset: 0, count: 20 }
);Collection Operations
const collection = new FlongoCollection<User>('users');
// Create
const user = await collection.create({
name: 'John Doe',
email: '[email protected]',
age: 30,
tags: ['developer']
});
// Read
const user = await collection.get('user123');
const users = await collection.getAll(query);
const first = await collection.getFirst(query);
const count = await collection.count(query);
const exists = await collection.exists(query);
// Update
await collection.update('user123', { age: 31 });
await collection.updateAll({ status: 'verified' }, query);
await collection.increment('user123', 'loginCount', 1);
await collection.append('user123', 'tags', ['admin']);
// Delete
await collection.delete('user123');
await collection.batchDelete(['user1', 'user2']);
// Batch operations
await collection.batchCreate([user1, user2, user3]);Configuration
// Disable event logging
const collection = new FlongoCollection<User>('users', {
enableEventLogging: false
});
// Custom events collection
const collection = new FlongoCollection<User>('users', {
enableEventLogging: true,
eventsCollectionName: 'audit_logs'
});Examples
E-commerce Product Search
interface Product {
name: string;
price: number;
category: string;
tags: string[];
inStock: boolean;
rating: number;
}
const products = new FlongoCollection<Product>('products');
// Find affordable, well-rated tech products in stock
const results = await products.getAll(
new FlongoQuery()
.where('category').eq('electronics')
.and('price').ltEq(500)
.and('rating').gtEq(4.0)
.and('inStock').eq(true)
.and('tags').arrContainsAny(['laptop', 'phone', 'tablet'])
.orderBy('rating', SortDirection.Descending)
);User Management
interface User {
email: string;
role: string;
lastLogin: number;
preferences: string[];
location?: Coordinates;
}
const users = new FlongoCollection<User>('users');
// Find active users who haven't logged in recently
const staleUsers = await users.getAll(
new FlongoQuery()
.where('role').neq('admin')
.and('lastLogin').lt(Date.now() - 30 * 24 * 60 * 60 * 1000) // 30 days ago
.orderBy('lastLogin', SortDirection.Ascending)
);
// Find users interested in specific topics near a location
const nearbyDevs = await users.getAll(
new FlongoQuery()
.where('preferences').arrContainsAny(['javascript', 'react', 'node'])
.and('location').inRadius(
'location',
{ latitude: 37.7749, longitude: -122.4194 }, // San Francisco
10000 // 10km radius
)
);Error Handling
import { Error404, Error400 } from 'flongo';
try {
const user = await users.get('nonexistent-id');
} catch (error) {
if (error instanceof Error404) {
console.log('User not found');
}
}Migration from Firestore
Flongo's API closely mirrors Firestore, making migration straightforward:
// Firestore
const snapshot = await db.collection('users')
.where('age', '>=', 18)
.where('tags', 'array-contains-any', ['developer', 'designer'])
.orderBy('name')
.get();
// Flongo
const users = await collection.getAll(
new FlongoQuery()
.where('age').gtEq(18)
.and('tags').arrContainsAny(['developer', 'designer'])
.orderBy('name')
);License
MIT
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
