One query, three shapes
A production query lives three lives. It starts as a thought in SQL, runs as a MongoDB command, and finally ships inside application code. Keeping the three in sync by hand is where bugs are born.
Take an unremarkable query:
SELECT displayName, active, score
FROM customers
WHERE active = true
Shape one: the MongoDB command
As a MongoDB operation this is not even an aggregation — a find with a
projection is enough:
db.customers.find(
{ active: true },
{ displayName: 1, active: 1, score: 1 }
)
Knowing when a SQL query degrades into a full pipeline (a GROUP BY, a
JOIN, a computed column) and when it stays a cheap find is half the craft.
Shape two: the C# driver code
The same query in the official C# driver wants a typed model and a typed filter:
public sealed class Customer
{
[BsonId]
public int Id { get; set; }
[BsonElement("displayName")]
public string? DisplayName { get; set; }
[BsonElement("active")]
public bool Active { get; set; }
[BsonElement("score")]
public int Score { get; set; }
}
var results = await database
.GetCollection<Customer>("customers")
.Find(c => c.Active)
.ToListAsync();
Notice how much of this is derivable: the field names, the BSON attributes, the filter expression. None of it deserves to be typed by hand.
Shape three: LINQ
For teams that live in LINQ, the same operation reads almost like the SQL it came from:
var results = await collection.AsQueryable()
.Where(c => c.Active)
.Select(c => new { c.DisplayName, c.Active, c.Score })
.ToListAsync();
Generate the boring parts
The transitions between these shapes are mechanical, and mechanical work belongs to tooling. TableCore renders the query you wrote as mongosh, C# driver code or C# LINQ — generated from the exact command the application would send, so what you paste into your codebase is what actually ran against your data. Which SQL gets that far is listed in SQL support.
Start with the browser-based SQL to MongoDB converter to see the
database-side shape. For queries that need a pipeline, read how GROUP BY
maps to $group and how a SQL
JOIN maps to $lookup before
generating the corresponding application code.