@dataql/mongodb-adapter
Version:
MongoDB adapter for DataQL with zero API changes
428 lines (318 loc) • 10.2 kB
Markdown
# DataQL MongoDB Adapter
MongoDB Node.js Driver API adapter for DataQL - Migrate from MongoDB to DataQL with zero API changes.
## Installation
```bash
npm install @dataql/mongodb-adapter
```
## Quick Start
```typescript
import { MongoClient } from "@dataql/mongodb-adapter";
const client = new MongoClient("mongodb://localhost:27017/mydb", {
dataql: {
env: "prod",
},
});
await client.connect();
const db = client.db("myapp");
const collection = db.collection("users");
// Use familiar MongoDB operations
const result = await collection.insertOne({
name: "John Doe",
email: "john@example.com",
});
const users = await collection.find({ name: "John Doe" }).toArray();
console.log(users);
await client.close();
```
## Features
- **Zero API Changes**: Drop-in replacement for MongoDB Node.js driver
- **Full MongoDB API Compatibility**: All major operations supported
- **ObjectId Support**: Complete ObjectId implementation with utilities
- **Cursor Operations**: Full cursor support with chaining methods
- **Bulk Operations**: Efficient bulk write operations
- **TypeScript Support**: Full type safety and IntelliSense
- **DataQL Infrastructure**: No direct database connections - routes through DataQL's secure infrastructure
- **DataQL Benefits**: Offline-first, real-time sync, automatic scaling
## Architecture
This adapter works through DataQL's infrastructure rather than connecting directly to MongoDB:
```
MongoDB Adapter → DataQL Core → Worker → Lambda → MongoDB
```
**Key Points:**
- ✅ **No Direct Database Connections**: All operations route through DataQL's infrastructure
- ✅ **Database Isolation**: Each client gets their own dedicated database
- ✅ **Automatic Routing**: MongoDB URL is used for routing, not direct connection
- ✅ **Infrastructure Benefits**: Automatic scaling, caching, offline support
## API Reference
### MongoClient
```typescript
import { MongoClient, connect } from "@dataql/mongodb-adapter";
// Constructor
const client = new MongoClient(url, options);
// Static connect method
const client = await MongoClient.connect(url, options);
// Helper function
const client = await connect(url, options);
```
#### Options
```typescript
interface MongoClientOptions {
// MongoDB compatibility options (ignored but supported for zero-API-change migration)
useNewUrlParser?: boolean;
useUnifiedTopology?: boolean;
maxPoolSize?: number;
serverSelectionTimeoutMS?: number;
// DataQL configuration - operations route through DataQL infrastructure
// Architecture: Client → Worker → Lambda → MongoDB (no direct database connections)
dataql?: {
appToken?: string;
env?: "dev" | "prod";
devPrefix?: string;
customConnection?: any; // For routing through other SDKs
};
}
```
### Database Operations
```typescript
const db = client.db("database_name");
// Get collection
const collection = db.collection("collection_name");
// Database utilities
await db.listCollections();
await db.dropCollection("collection_name");
await db.dropDatabase();
await db.stats();
```
### Collection Operations
#### Insert Operations
```typescript
// Insert one document
const result = await collection.insertOne(document);
console.log(result.insertedId);
// Insert multiple documents
const result = await collection.insertMany(documents);
console.log(result.insertedIds);
```
#### Find Operations
```typescript
// Find with cursor
const cursor = collection.find(filter, options);
const documents = await cursor.toArray();
// Find one document
const document = await collection.findOne(filter, options);
// Find with cursor methods
const results = await collection
.find({ status: "active" })
.sort({ createdAt: -1 })
.limit(10)
.skip(20)
.toArray();
```
#### Update Operations
```typescript
// Update one document
const result = await collection.updateOne(filter, update, options);
// Update multiple documents
const result = await collection.updateMany(filter, update, options);
// Replace one document
const result = await collection.replaceOne(filter, replacement, options);
// Find and update
const result = await collection.findOneAndUpdate(filter, update, {
returnDocument: "after",
});
```
#### Delete Operations
```typescript
// Delete one document
const result = await collection.deleteOne(filter);
// Delete multiple documents
const result = await collection.deleteMany(filter);
// Find and delete
const result = await collection.findOneAndDelete(filter);
```
#### Bulk Operations
```typescript
const operations = [
{ insertOne: { document: { name: "Alice" } } },
{ updateOne: { filter: { name: "Bob" }, update: { $set: { age: 30 } } } },
{ deleteOne: { filter: { name: "Charlie" } } },
];
const result = await collection.bulkWrite(operations);
```
#### Count and Aggregation
```typescript
// Count documents
const count = await collection.countDocuments(filter);
const estimatedCount = await collection.estimatedDocumentCount();
// Get distinct values
const values = await collection.distinct("fieldName", filter);
// Basic aggregation (limited support)
const results = await collection.aggregate(pipeline).toArray();
```
### ObjectId
```typescript
import { ObjectId, BSON } from "@dataql/mongodb-adapter";
// Create ObjectId
const id = new ObjectId();
const idFromString = new ObjectId("507f1f77bcf86cd799439011");
// ObjectId methods
console.log(id.toString());
console.log(id.toHexString());
console.log(id.getTimestamp());
console.log(id.equals(otherId));
// Static methods
console.log(ObjectId.isValid(idString));
const id2 = ObjectId.createFromHexString(hexString);
// BSON utilities
const id3 = new BSON.ObjectId();
```
### Cursor Operations
```typescript
const cursor = collection.find(filter);
// Get all results
const documents = await cursor.toArray();
// Iterate through results
await cursor.forEach((doc) => console.log(doc));
// Cursor transformations
const transformedCursor = cursor
.limit(10)
.skip(5)
.sort({ name: 1 })
.project({ name: 1, email: 1 });
// Async iteration
for await (const doc of cursor) {
console.log(doc);
}
// Manual iteration
while (await cursor.hasNext()) {
const doc = await cursor.next();
console.log(doc);
}
```
## Migration Guide
### From MongoDB Driver
Replace your MongoDB driver import with the DataQL MongoDB adapter:
```typescript
// Before
import { MongoClient } from "mongodb";
// After
import { MongoClient } from "@dataql/mongodb-adapter";
```
All your existing MongoDB code will work without changes!
### Configuration
Add DataQL configuration to your MongoDB connection options:
```typescript
const client = new MongoClient(connectionString, {
// Your existing MongoDB options (for compatibility)
useNewUrlParser: true,
useUnifiedTopology: true,
// Add DataQL configuration
dataql: {
appToken: "your-app-token", // Required for DataQL routing
env: process.env.NODE_ENV === "production" ? "prod" : "dev",
devPrefix: "myapp_", // Optional prefix for dev environments
},
});
```
## Examples
### Basic CRUD Operations
```typescript
import { MongoClient } from "@dataql/mongodb-adapter";
async function basicCrud() {
const client = new MongoClient("mongodb://localhost:27017");
await client.connect();
const db = client.db("myapp");
const users = db.collection("users");
// Create
const user = await users.insertOne({
name: "Alice Johnson",
email: "alice@example.com",
age: 28,
});
// Read
const foundUser = await users.findOne({ _id: user.insertedId });
// Update
await users.updateOne({ _id: user.insertedId }, { $set: { age: 29 } });
// Delete
await users.deleteOne({ _id: user.insertedId });
await client.close();
}
```
### Advanced Queries
```typescript
async function advancedQueries() {
const client = new MongoClient("mongodb://localhost:27017");
await client.connect();
const db = client.db("ecommerce");
const products = db.collection("products");
// Complex query with multiple conditions
const results = await products
.find({
category: "electronics",
price: { $gte: 100, $lte: 1000 },
inStock: true,
})
.sort({ price: -1 })
.limit(20)
.project({ name: 1, price: 1, rating: 1 })
.toArray();
console.log("Products:", results);
await client.close();
}
```
### Bulk Operations
```typescript
async function bulkOperations() {
const client = new MongoClient("mongodb://localhost:27017");
await client.connect();
const db = client.db("inventory");
const items = db.collection("items");
const operations = [
{
insertOne: {
document: {
sku: "ABC123",
name: "Widget",
quantity: 100,
},
},
},
{
updateOne: {
filter: { sku: "DEF456" },
update: { $inc: { quantity: -5 } },
upsert: true,
},
},
{
deleteOne: {
filter: { quantity: { $lte: 0 } },
},
},
];
const result = await items.bulkWrite(operations);
console.log("Bulk result:", result);
await client.close();
}
```
## Limitations
While the adapter provides comprehensive MongoDB API compatibility, some advanced features have limitations:
1. **Aggregation Pipeline**: Basic support only - complex aggregations may not work as expected
2. **Transactions**: Not supported (DataQL handles consistency differently)
3. **GridFS**: Not supported
4. **Change Streams**: Not supported (DataQL provides real-time updates differently)
5. **Text Search**: Limited support
6. **Geospatial Queries**: Limited support
## DataQL Benefits
By using this adapter, you get all the benefits of DataQL:
- **Offline-First**: Your app works without internet connection
- **Real-Time Sync**: Automatic data synchronization across devices
- **Automatic Scaling**: No need to manage database infrastructure
- **Type Safety**: Full TypeScript support with schema validation
- **Zero Latency**: Local-first architecture for instant responses
## Support
- [DataQL Documentation](https://docs.dataql.com)
- [GitHub Issues](https://github.com/dataql/dataql/issues)
- [Discord Community](https://discord.gg/dataql)
## License
MIT