Queryleaf
SQL for Mongo (in Node JS)
Install / Use
/learn @beekeeper-studio/QueryleafREADME
Overview
QueryLeaf is a library that translates SQL queries into MongoDB commands. It parses SQL using node-sql-parser, transforms it into an abstract command set, and then executes those commands against the MongoDB Node.js driver.
Features
- Parse SQL statements into an abstract syntax tree using node-sql-parser
- Compile SQL AST into MongoDB commands
- Execute MongoDB commands using the official driver
- Support for basic SQL operations:
- SELECT
- INSERT
- UPDATE
- DELETE
- Advanced querying features:
- Nested field access (e.g.,
address.zip) - Array element access (e.g.,
items[0].name) - GROUP BY with aggregation functions (COUNT, SUM, AVG, MIN, MAX)
- JOINs between collections
- Nested field access (e.g.,
- Multiple interfaces:
- Library for direct integration in your code
- CLI for command-line SQL queries
- Web Server for REST API access
- PostgreSQL Wire Protocol Server for connecting with standard PostgreSQL clients
SQL to MongoDB Translation Examples
QueryLeaf translates SQL queries into MongoDB commands. Here are some examples of the translation:
Basic SELECT with WHERE
SQL:
SELECT name, email FROM users WHERE age > 21
MongoDB:
db.collection('users').find(
{ age: { $gt: 21 } },
{ name: 1, email: 1 }
)
Nested Field Access
SQL:
SELECT name, address.city, address.zip FROM users WHERE address.city = 'New York'
MongoDB:
db.collection('users').find(
{ 'address.city': 'New York' },
{ name: 1, 'address.city': 1, 'address.zip': 1 }
)
Array Element Access
SQL:
SELECT _id, items[0].name, items[0].price FROM orders WHERE items[0].price > 1000
MongoDB:
db.collection('orders').find(
{ 'items.0.price': { $gt: 1000 } },
{ _id: 1, 'items.0.name': 1, 'items.0.price': 1 }
)
GROUP BY with Aggregation
SQL:
SELECT status, COUNT(*) as count, SUM(total) as total_amount FROM orders GROUP BY status
MongoDB:
db.collection('orders').aggregate([
{
$group: {
_id: "$status",
status: { $first: "$status" },
count: { $sum: 1 },
total_amount: { $sum: "$total" }
}
}
])
JOIN Between Collections
SQL:
SELECT u.name, o._id as order_id, o.total FROM users u JOIN orders o ON u._id = o.userId
MongoDB:
db.collection('users').aggregate([
{
$lookup: {
from: "orders",
localField: "_id",
foreignField: "userId",
as: "orders"
}
},
{ $unwind: { path: "$orders", preserveNullAndEmptyArrays: true } },
{
$project: {
name: 1,
order_id: "$orders._id",
total: "$orders.total"
}
}
])
Installation
npm install @queryleaf/lib
Usage
QueryLeaf takes your existing MongoDB client. It never creates or manages MongoDB connections on its own.
import { QueryLeaf } from '@queryleaf/lib';
import { MongoClient } from 'mongodb';
// Your existing MongoDB client
const mongoClient = new MongoClient('mongodb://localhost:27017');
await mongoClient.connect();
// Create QueryLeaf with your MongoDB client
const queryLeaf = new QueryLeaf(mongoClient, 'mydatabase');
// Execute SQL queries against your MongoDB database
const results = await queryLeaf.execute('SELECT * FROM users WHERE age > 21');
console.log(results);
// When you're done, close your MongoDB client
// (QueryLeaf never manages MongoDB connections)
await mongoClient.close();
Testing with DummyQueryLeaf
For testing or debugging without a real database, use DummyQueryLeaf:
import { DummyQueryLeaf } from '@queryleaf/lib';
// Create a DummyQueryLeaf instance for testing
const queryLeaf = new DummyQueryLeaf('mydatabase');
// Operations will be logged to console but not executed
await queryLeaf.execute('SELECT * FROM users WHERE age > 21');
// [DUMMY MongoDB] FIND in mydatabase.users with filter: { "age": { "$gt": 21 } }
// [DUMMY MongoDB] Executing find on users
Examples
The repository includes several examples:
src/examples/existing-client-demo.ts- Shows how to use QueryLeaf in a real applicationsrc/examples/basic-usage.ts- Demonstrates basic usage with an existing MongoDB clientsrc/examples/dummy-client-demo.ts- Shows how to use DummyQueryLeaf for testing
You can run the examples with:
# Main application example
ts-node src/examples/existing-client-demo.ts
# Basic usage example
npm run example
# Dummy client example
ts-node src/examples/dummy-client-demo.ts
SQL Query Examples
Here are some practical SQL queries you can use with QueryLeaf:
Working with Nested Fields
-- Query users by nested address field
SELECT name, email, address.city FROM users WHERE address.zip = '10001'
-- Insert with nested document structure
INSERT INTO users (name, age, email, address) VALUES
('Jane Smith', 28, 'jane@example.com', {
"street": "456 Park Ave",
"city": "Chicago",
"state": "IL",
"zip": "60601"
})
-- Update a nested field
UPDATE users SET address.city = 'San Francisco', address.state = 'CA' WHERE _id = '123'
Working with Array Fields
-- Query by array element property
SELECT userId, total FROM orders WHERE items[0].name = 'Laptop'
-- Filter by array element condition
SELECT * FROM orders WHERE items[1].price < 50
-- Insert document with array field
INSERT INTO orders (userId, items, status) VALUES
('user123', [
{ "id": "prod1", "name": "Monitor", "price": 300 },
{ "id": "prod2", "name": "Keyboard", "price": 75 }
], 'pending')
Advanced Queries
-- Using GROUP BY with aggregation functions
SELECT category, COUNT(*) as count, AVG(price) as avg_price FROM products GROUP BY category
-- JOIN between users and orders
SELECT u.name, o.total, o.status FROM users u JOIN orders o ON u._id = o.userId WHERE o.total > 100
Check out the examples folder for more complete examples, including how to set up the QueryLeaf instance and execute these queries.
This library demonstrates:
- Basic SELECT queries
- Filtering with WHERE clauses
- Sorting with ORDER BY
- INSERT, UPDATE, and DELETE operations
- Accessing nested fields with dot notation
- Accessing array elements with indexing
- Aggregation with GROUP BY and aggregation functions
- Joining collections with JOIN syntax
Architecture
QueryLeaf follows a modular architecture:
- SqlParser: Converts SQL text into an abstract syntax tree (AST) using node-sql-parser
- SqlCompiler: Transforms the AST into MongoDB commands
- CommandExecutor: Executes the commands against a MongoDB database
Development
Testing
The project includes both unit tests and integration tests:
Unit Tests
Run unit tests with:
npm run test:unit
Unit tests are located in the tests/unit directory and focus on testing the parsing and compilation of SQL statements without requiring a database connection.
Integration Tests
Integration tests use testcontainers to spin up a MongoDB instance in Docker. Make sure you have Docker installed and running before executing these tests.
Run integration tests with:
npm run test:integration
Integration tests are located in the tests/integration directory and test the complete functionality with a real MongoDB database.
These tests will:
- Start a MongoDB container
- Load fixture data
- Run a series of SQL queries against the database
- Verify the results
- Clean up the container when done
To run all tests:
npm run test
Continuous Integration
This project uses GitHub Actions for continuous integration. The CI workflow automatically runs on:
- All pushes to the
mainbranch - All pull requests targeting the
mainbranch
The CI workflow:
- Sets up Node.js (versions 16.x, 18.x, and 20.x)
- Installs dependencies
- Runs unit tests
- Runs integration tests with MongoDB in a Docker container
- Performs type checking
- Builds the package
You can see the workflow configuration in .github/workflows/test.yml.
Documentation
Comprehensive documentation is available at queryleaf.com/docs, including:
- Detailed installation and setup guides
- In-depth explanation of supported SQL syntax
- Usage examples and best practices
- Troubleshooting and debugging guides
- Performance optimization tips
For local development, you can run the documentation site with:
# Install required packages
pip install -r requirements.txt
# Serve the documentation locally
npm run docs:serve
License
QueryLeaf is dual-licensed:
- AGPL-3.0 for open source use
- Commercial license for commercial use with embedding
For commercial licensing options and pricing, please visit queryleaf.com or contact us at info@queryleaf.com.
Related Skills
oracle
341.8kBest practices for using the oracle CLI (prompt + file bundling, engines, sessions, and file attachment patterns).
prose
341.8kOpenProse VM skill pack. Activate on any `prose` command, .prose files, or OpenProse mentions; orchestrates multi-agent workflows.
Writing Hookify Rules
84.6kThis skill should be used when the user asks to "create a hookify rule", "write a hook rule", "configure hookify", "add a hookify rule", or needs guidance on hookify rule syntax and patterns.
Command Development
84.6kThis skill should be used when the user asks to "create a slash command", "add a command", "write a custom command", "define command arguments", "use command frontmatter", "organize commands", "create command with file references", "interactive command", "use AskUserQuestion in command", or needs guidance on slash command structure, YAML frontmatter fields, dynamic arguments, bash execution in commands, user interaction patterns, or command development best practices for Claude Code.
