BaseQL
BaseQL is Singlebase's unified query language for all operations. Inspired by MongoDB's powerful operators, BaseQL simplifies the syntax and extends it across your entire backend - not just databases.
Overview
BaseQL - One language for your entire backend. Simple JSON structure, powerful operators, and dynamic expressions that work consistently across database queries, authentication, file storage, AI operations, and vector search.
Key features:
- Unified syntax across all APIs
- MongoDB-inspired operators with cleaner syntax
- Built-in expressions and transformations
- Learn once, use everywhere
Basic Syntax
Every BaseQL request is a JSON object with an op field:
json
{
"op": "operation_name",
"collection": "collection_name",
"filter": { },
"data": { }
}Required field:
op- The operation to perform
Common fields:
collection- Target collectionfilter- Match criteria (Filter Operators)data- Data to insert/update (Data Operators)output- Result formatting (Output Expressions)limit,offset,page,per_page- Paginationsort- Sortinglookup- Joins
Dot Notation
Access nested fields using dot notation anywhere in BaseQL:
json
{
"filter": {
"user.profile.age:$gte": 18,
"address.city": "New York"
},
"data": {
"user.name": "John Doe",
"stats.score:$incr": 10
},
"output": {
"$city": "address.city",
"location": "{{ address.city }}, {{ address.state }}"
}
}Filter Operators
Match documents in filter using :$operator syntax.
json
{
"filter": {
"age:$gte": 18,
"price:$between": [10, 100],
"status:$in": ["active", "premium"],
"tags:$includes": "featured",
"$or": [
{ "role": "admin" },
{ "verified": true }
]
}
}Data Operators
Transform data in data using :$operator syntax.
json
{
"data": {
"name": "John Doe",
"score:$incr": 10,
"credits:$decr": 5,
"tags:$push": "premium",
"created_at:$now": true,
"id:$uuid4": true
}
}Template Expressions
Dynamic transformations using expressions in data and output.
json
{
"greeting": "Hello {{ name }}!",
"total": "?{{ price * quantity }}",
"$full_name": "first_name + ' ' + last_name",
"formatted_date": "{{ @formatdate(created_at, 'YYYY-MM-DD') }}",
"$item_count": "@len(items)"
}Expression types:
{{ expr }}- String template?{{ expr }}- Native type (number, boolean)$field- Shorthand for native type@function()- Helper functions
View Template Expressions →
View Helper Functions →
Output Expressions
Reshape query results in output.
json
{
"output": {
"display_name": "{{ first_name }} {{ last_name }}",
"$age": "age",
"is_adult": "?{{ age >= 18 }}"
}
}Select specific fields:
json
{ "output": "{name, email, age}" }Select all fields:
json
{ "output": "**" }Extend all fields:
json
{
"output": {
"_": "**",
"$full_name": "first_name + ' ' + last_name"
}
}Examples
Query
json
{
"op": "db.find",
"collection": "products",
"filter": {
"price:$between": [10, 100],
"category:$in": ["electronics", "gadgets"],
"stock:$gt": 0
},
"sort": "price asc",
"limit": 20
}Update
json
{
"op": "db.update",
"collection": "users",
"data": {
"_key": "user_123",
"name": "Jane Doe",
"score:$incr": 50,
"tags:$push": "premium",
"last_login:$now": true
}
}Insert with Calculations
json
{
"op": "db.insert",
"collection": "orders",
"data": {
"order_id:$uuid4": true,
"user_id": "user_123",
"items": [{ "name": "Widget", "price": 29.99, "qty": 2 }],
"$subtotal": "@sum(@map(items, 'price * qty'))",
"tax": "?{{ subtotal * 0.08 }}",
"total": "?{{ subtotal + tax }}",
"created_at:$now": true
}
}Query with Output
json
{
"op": "db.find",
"collection": "users",
"filter": { "status": "active" },
"output": {
"display_name": "{{ first_name }} {{ last_name }}",
"$age": "age",
"member_since": "{{ @formatdate(_created_at, 'YYYY') }}"
}
}Authentication
json
{
"op": "auth.signup",
"email": "user@example.com",
"password": "SecurePass123",
"display_name": "John Doe"
}File Upload
json
{
"op": "file.presign_upload",
"filename": "photo.jpg",
"content_type": "image/jpeg",
"public_read": true
}Vector Search
json
{
"op": "vdb.search",
"query": "machine learning tutorials",
"collection": "knowledge_base"
}AI Text
json
{
"op": "baseai.create",
"input": "Write a product description for wireless headphones",
"content_length": 200
}Quick Reference
Structure:
json
{
"op": "operation",
"collection": "name",
"filter": { "field:$operator": "value" },
"data": { "field:$operator": "value" },
"output": { "$field": "expression" },
"sort": "field asc|desc",
"limit": 50
}Operators:
- Filter:
:$gt,:$gte,:$lt,:$lte,:$eq,:$ne,:$in,:$nin,:$between,:$includes,:$all,:$any,$or,$nor - Data:
:$incr,:$decr,:$push,:$lpush,:$pop,:$lpop,:$extend,:$lextend,:$addset,:$remove,:$clear,:$now,:$timestamp,:$uuid,:$uuid4,:$uuid7
Expressions:
{{ expr }}- String?{{ expr }}- Native type$field- Shorthand@function()- Helpers
APIs:
db.*- Database operationsauth.*- Authenticationfile.*- File storagevdb.*- Vector searchbaseai.*- AI text processing
BaseQL vs MongoDB
For developers familiar with MongoDB:
Query
MongoDB:
js
db.users.find({
age: { $gte: 18 },
status: { $in: ["active", "premium"] }
})BaseQL:
json
{
"op": "db.find",
"collection": "users",
"filter": {
"age:$gte": 18,
"status:$in": ["active", "premium"]
}
}Update
MongoDB:
js
db.users.updateOne(
{ _id: "user_123" },
{
$set: { name: "Jane" },
$inc: { score: 10 },
$push: { tags: "premium" }
}
)BaseQL:
json
{
"op": "db.update",
"collection": "users",
"filter": { "_key": "user_123" },
"data": {
"name": "Jane",
"score:$incr": 10,
"tags:$push": "premium"
}
}Aggregation
MongoDB:
js
db.orders.aggregate([
{ $match: { status: "completed" } },
{
$project: {
total: { $multiply: ["$price", "$quantity"] },
displayName: { $concat: ["$firstName", " ", "$lastName"] }
}
}
])BaseQL:
json
{
"op": "db.find",
"collection": "orders",
"filter": { "status": "completed" },
"output": {
"total": "?{{ price * quantity }}",
"display_name": "{{ first_name }} {{ last_name }}"
}
}or with $
json
{
"op": "db.find",
"collection": "orders",
"filter": { "status": "completed" },
"output": {
"$total": "price * quantity",
"display_name": "{{ first_name }} {{ last_name }}"
}
}Complex Query
MongoDB:
js
db.products.find({
price: { $gte: 10, $lte: 100 },
category: { $in: ["electronics", "gadgets"] },
stock: { $gt: 0 }
}).sort({ price: 1 }).limit(20)BaseQL:
json
{
"op": "db.find",
"collection": "products",
"filter": {
"price:$between": [10, 100],
"category:$in": ["electronics", "gadgets"],
"stock:$gt": 0
},
"sort": "price asc",
"limit": 20
}Complex Update
MongoDB:
js
db.users.updateOne(
{ _id: "user_123" },
{
$set: { name: "Jane Doe", status: "active" },
$inc: { score: 50, login_count: 1 },
$push: { tags: "premium" },
$currentDate: { last_login: true }
}
)BaseQL:
json
{
"op": "db.update",
"collection": "users",
"filter": { "_key": "user_123" },
"data": {
"name": "Jane Doe",
"status": "active",
"score:$incr": 50,
"login_count:$incr": 1,
"tags:$push": "premium",
"last_login:$now": true
}
}Projection
MongoDB:
js
db.orders.aggregate([
{ $match: { status: "completed" } },
{
$project: {
orderId: "$_id",
displayTotal: { $concat: ["$", { $toString: "$total" }] },
itemCount: { $size: "$items" }
}
}
])BaseQL:
json
{
"op": "db.find",
"collection": "orders",
"filter": { "status": "completed" },
"output": {
"$order_id": "_key",
"display_total": "${{ total }} USD",
"$item_count": "@len(items)"
}
}Insert with Calculations
MongoDB:
js
// Requires separate calculation, then insert
const subtotal = items.reduce((sum, i) => sum + (i.price * i.qty), 0);
const tax = subtotal * 0.08;
const total = subtotal + tax;
db.orders.insertOne({
order_id: new UUID(),
user_id: "user_123",
items: items,
subtotal: subtotal,
tax: tax,
total: total,
created_at: new Date()
});BaseQL:
json
{
"op": "db.insert",
"collection": "orders",
"data": {
"order_id:$uuid4": true,
"user_id": "user_123",
"items": [{ "name": "Widget", "price": 29.99, "qty": 2 }],
"$subtotal": "@sum(@map(items, 'price * qty'))",
"tax": "?{{ subtotal * 0.08 }}",
"total": "?{{ subtotal + tax }}",
"created_at:$now": true
}
}Sorting
MongoDB:
js
db.products.find().sort({ category: 1, price: -1 })BaseQL:
json
{
"op": "db.find",
"collection": "products",
"sort": "category asc, price desc"
}Joins
MongoDB:
js
db.orders.aggregate([
{
$lookup: {
from: "users",
localField: "user_id",
foreignField: "_id",
as: "user"
}
}
])BaseQL:
json
{
"op": "db.find",
"collection": "orders",
"lookup": {
"user": {
"collection": "users",
"on": "user_key"
}
}
}Key advantages:
- Same familiar operators (
$gte,$in,$push, etc.) - Cleaner inline syntax - no nested structures
- Works across DB + Auth + Files + AI + Vector
- Expressions replace complex aggregation pipelines
- One operation does it all - no separate calculation steps
- Simpler to read and write