UNPKG

@dataql/mongodb-adapter

Version:

MongoDB adapter for DataQL with zero API changes

428 lines (318 loc) 10.2 kB
# 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