SQL to NoSQL Query Converter
Translate SQL SELECT, WHERE, and JOIN queries into MongoDB aggregation pipelines or PostgreSQL JSON functions. Compare syntax side by side.
Paste your SQL query
Convert a SQL SELECT query into a MongoDB aggregation pipeline
You are migrating a MySQL database to MongoDB and you have a stack of SQL queries that your app relies on. This tool takes each SELECT statement and outputs the equivalent MongoDB aggregation pipeline so you can see exactly how the query translates β without spending hours reading MongoDB docs.
Step 1: Paste your SQL query
Type or paste a SELECT query into the SQL input field. The tool understands WHERE conditions with AND/OR, ORDER BY, LIMIT, GROUP BY with aggregate functions (COUNT, SUM, AVG, MIN, MAX), and JOIN or LEFT JOIN clauses. A SELECT * query against a users table is the simplest starting point β the converter outputs a pipeline with no stages since MongoDB returns all documents by default.
Step 2: Pick your output format
Choose between MongoDB Shell, Node.js Driver, or Mongoose. All three produce the same aggregation pipeline β only the surrounding boilerplate differs. MongoDB Shell outputs db.collection.aggregate([...]) which you can paste into a terminal. Node.js Driver outputs async code using the official mongodb package. Mongoose outputs Model.aggregate() code. Pick the format that matches your project.
Step 3: Review the pipeline stages
Below the output, a colour-coded panel shows each aggregation stage in order. A $match stage comes from your WHERE clause, $sort from ORDER BY, $group from GROUP BY, and $lookup from JOINs. Each stage includes a brief description of what it does. Check the pipeline order β $match should generally come before $group to filter early and reduce the amount of data flowing through the pipeline.
Step 4: Copy and adapt
Click the copy button to grab the generated code. The converter gives you a working starting point β you may still need to adjust field names, add index hints, or handle edge cases specific to your schema. For example, a SQL BETWEEN clause translates to $gte and $lte in MongoDB, but you might need to add a $type stage if the field stores mixed types.
How the SQL to NoSQL conversion works
SQL parsing happens in three steps
The converter first tokenises your SQL input using a regular expression that preserves quoted strings and numeric literals. It then splits the token stream into clause blocks β SELECT, FROM, WHERE, JOIN, GROUP BY, ORDER BY, LIMIT β by scanning for keyword positions. Each block body is parsed by a dedicated sub-parser. The SELECT sub-parser handles aggregate functions, column aliases, and table-qualified field names. The WHERE sub-parser handles AND/OR logic and operator mapping. The result is a structured abstract syntax tree that the pipeline builder consumes.
Each SQL clause maps to a MongoDB aggregation stage
The pipeline builder walks the AST and emits MongoDB stages in the correct order. JOINs become $lookup followed by $unwind. WHERE conditions map operators directly β equals becomes $eq, greater-than becomes $gt, LIKE becomes $regex, and BETWEEN becomes a combined $gte/$lte. AND logic produces an $and array and OR logic produces an $or array. GROUP BY triggers a $group stage with accumulator expressions like $sum and $avg. ORDER BY maps to $sort, LIMIT to $limit, and SELECT column list to $project. The pipeline is built in the order MongoDB expects: $match first for early filtering, then $lookup, $unwind, $group, $sort, $project, and $limit.
Why $unwind follows $lookup
MongoDB's $lookup always returns matched documents as an array, even when a single document matches. For a standard JOIN (not LEFT JOIN), the converter adds an $unwind stage to flatten this array into individual documents, matching SQL INNER JOIN behaviour where each match produces one row. For LEFT JOINs, $unwind includes preserveNullAndEmptyArrays: true so unmatched documents are retained with a null value instead of being dropped.
Output wrapping is the only difference between formats
Once the pipeline array is built, the output formatter wraps it in the syntax required by your chosen target. MongoDB Shell outputs db.collection.aggregate([...]) for direct pasting into a terminal. Node.js Driver outputs an async function using the official mongodb package with connection handling. Mongoose outputs a Model.aggregate() call with schema-aware model references. All three produce identical aggregation logic β only the surrounding boilerplate differs.
A concrete conversion example
Consider: SELECT u.name, COUNT(o.id) AS order_count FROM users u JOIN orders o ON u.id = o.user_id WHERE u.active = 1 GROUP BY u.name ORDER BY order_count DESC LIMIT 10. The converter produces a pipeline with $match (filter active users), $lookup (join orders on user_id), $unwind (flatten the orders array), $group (group by name, count orders), $sort (descending by order_count), and $limit (top 10). The generated code wraps this pipeline in your chosen output format, ready to paste into your project.
Frequently asked questions
What SQL statements does this tool support?
The converter handles SELECT queries including WHERE conditions with AND/OR, ORDER BY, LIMIT, GROUP BY with aggregate functions (COUNT, SUM, AVG, MIN, MAX), and JOIN or LEFT JOIN clauses. INSERT, UPDATE, DELETE, and DDL statements are not supported β the focus is on read queries, which are the most common use case when migrating from SQL to MongoDB.
What is a MongoDB aggregation pipeline?
An aggregation pipeline is MongoDB's framework for data processing. Documents pass through a sequence of stages β $match, $project, $sort, $group, $lookup β with each stage transforming the data before passing it to the next. Pipelines are more powerful than simple find() queries and are the closest equivalent to complex SQL SELECT statements.
How are SQL JOINs translated?
SQL JOINs are converted to the $lookup aggregation stage, which performs a left outer join between two collections. The converter maps the JOIN's ON clause to the lookup fields: from (the foreign collection), localField, foreignField, and as (the output array field name). For standard JOINs, an additional $unwind stage flattens the joined array into individual documents.
Does the converter handle subqueries or nested SELECTs?
Not currently. The parser handles single-level SELECT queries with standard clauses. Subqueries and correlated subqueries require a more complex AST traversal and are beyond the scope of this tool. For complex queries, the converter provides a solid starting point that you can extend manually in your MongoDB code.
What is the difference between the three output formats?
MongoDB Shell produces mongosh syntax you can paste directly into a terminal. Node.js Driver outputs JavaScript code using the official mongodb package with async/await and connection handling. Mongoose generates code using the Mongoose ODM's Model.aggregate() method. All three produce the same pipeline β only the wrapper syntax differs.
Is my SQL query sent to any server?
No. The entire parsing and conversion runs locally in your browser using JavaScript. Your SQL queries never leave your device β there is no backend, no API call, and no data stored anywhere. This makes the tool suitable for converting queries that reference sensitive or proprietary database schemas.
Why does the pipeline include $unwind after $lookup?
MongoDB's $lookup always returns matched documents as an array, even when a single document matches. For standard JOINs, the converter adds $unwind to flatten this array into individual documents, matching SQL INNER JOIN behaviour. For LEFT JOINs, $unwind includes preserveNullAndEmptyArrays: true so unmatched documents are retained with a null value.
Can I convert COUNT(DISTINCT col) queries?
The current parser handles standard aggregate functions with a single field argument. COUNT(DISTINCT col) is not yet supported. For these cases, the converted pipeline gives you a working foundation β you can manually add $group accumulators with $addToSet and $size to approximate DISTINCT behaviour in MongoDB.