NoSQL Query Builder

The NoSQL query builder provides a fluent, chainable API for querying document databases — no raw BSON needed. It mirrors the SQL query builder's feel while adapting to document-store semantics.

Getting Started

import "github.com/CodeSyncr/nimbus/database/nosql"

// Start a query on a registered connection
var users []User
nosql.Query("mongo", "users").
    Where("active", true).
    Sort("name", nosql.Ascending).
    Limit(10).
    Get(ctx, &users)

// Or from the app-level *nimbus.NoSQL handle
store := nimbus.GetNoSQL()
nosql.QueryOn(store, "orders").
    Where("status", "pending").
    Latest().
    Get(ctx, &orders)

// Or on a specific driver instance
nosql.QueryOn(mongoDriver, "orders").
    Where("status", "pending").
    Latest().
    Get(ctx, &orders)

Filter Methods

MethodDescription
Where(field, value)Equality filter
Where(field, op, value)Operator filter — =, !=, >, >=, <, <=, in, nin, regex
WhereIn(field, values...)Match any of the values ($in)
WhereNotIn(field, values...)Exclude values ($nin)
WhereBetween(field, min, max)Range filter (inclusive)
WhereExists(field, bool)Check field existence
WhereNull(field)Field is null/missing
WhereNotNull(field)Field exists and is not null
WhereRegex(field, pattern)Regex match
WhereRaw(field, Document)Raw MongoDB operator map
OrWhere(conditions...)Combines filters with $or

Examples

// Equality
nosql.Query("mongo", "users").Where("active", true)

// Comparison operators
nosql.Query("mongo", "users").Where("age", ">=", 21)

// $in
nosql.Query("mongo", "orders").WhereIn("status", "pending", "processing")

// Range
nosql.Query("mongo", "products").WhereBetween("price", 10, 100)

// Regex
nosql.Query("mongo", "users").WhereRegex("name", "^Al")

// $or
nosql.Query("mongo", "users").OrWhere(
    nosql.Filter{"role": "admin"},
    nosql.Filter{"role": "superadmin"},
)

// Field existence
nosql.Query("mongo", "users").WhereExists("phone", true)
nosql.Query("mongo", "users").WhereNull("deleted_at")

// Raw operator
nosql.Query("mongo", "places").WhereRaw("location", nosql.Document{
    "$near": nosql.Document{
        "$geometry":    nosql.Document{"type": "Point", "coordinates": []float64{-73.97, 40.77}},
        "$maxDistance": 1000,
    },
})

Sort, Limit & Pagination

MethodDescription
Sort(field, order)Add a sort — nosql.Ascending or nosql.Descending
Latest(field?)Sort descending (default: created_at)
Oldest(field?)Sort ascending (default: created_at)
Limit(n)Limit results
Skip(n)Skip N documents
Select(fields...)Include only specified fields
Exclude(fields...)Exclude fields from results
// Latest 20 active users, only name & email
var users []User
nosql.Query("mongo", "users").
    Where("active", true).
    Latest().
    Limit(20).
    Select("name", "email").
    Get(ctx, &users)

// Paginate (page 2, 15 per page)
var orders []Order
page, err := nosql.Query("mongo", "orders").
    Where("status", "pending").
    Sort("created_at", nosql.Descending).
    Paginate(ctx, &orders, 2, 15)

fmt.Println(page.Total)       // total matching docs
fmt.Println(page.CurrentPage) // 2
fmt.Println(page.LastPage)    // calculated
fmt.Println(page.HasMore())   // true/false

Terminal Methods

MethodReturnsDescription
Get(ctx, &dest)errorFetch all matching documents
First(ctx, &dest)errorFetch the first matching document
FindByID(ctx, id, &dest)errorFetch a document by its ID
Count(ctx)int64, errorCount matching documents
Exists(ctx)bool, errorCheck if any match exists
Distinct(ctx, field)[]any, errorGet distinct values for a field

Mutation Methods

MethodReturnsDescription
Insert(ctx, doc)*InsertResult, errorInsert one document
InsertMany(ctx, docs)*InsertManyResult, errorInsert multiple documents
Update(ctx, update)*UpdateResult, errorUpdate first match
UpdateMany(ctx, update)*UpdateResult, errorUpdate all matches
Upsert(ctx, doc)*UpdateResult, errorInsert or update
Delete(ctx)*DeleteResult, errorDelete first match
DeleteMany(ctx)*DeleteResult, errorDelete all matches
// Insert via builder
res, _ := nosql.Query("mongo", "users").Insert(ctx, User{
    Name: "Dave", Email: "dave@example.com",
})

// Update matching docs
nosql.Query("mongo", "users").
    Where("role", "trial").
    Update(ctx, nosql.Filter{"role": "free"})

// Upsert
nosql.Query("mongo", "settings").
    Where("key", "site_name").
    Upsert(ctx, nosql.Filter{"key": "site_name", "value": "My App"})

// Delete inactive users
nosql.Query("mongo", "users").
    Where("active", false).
    DeleteMany(ctx)

Aggregation

// Run an aggregation pipeline through the builder
pipeline := bson.A{
    bson.D{{Key: "$group", Value: bson.D{
        {Key: "_id", Value: "$category"},
        {Key: "total", Value: bson.D{{Key: "$sum", Value: "$amount"}}},
    }}},
}
var results []bson.M
nosql.Query("mongo", "orders").Aggregate(ctx, pipeline, &results)

// Distinct values
statuses, _ := nosql.Query("mongo", "orders").
    Where("year", 2024).
    Distinct(ctx, "status")

Pagination

Paginate counts total documents, skips to the requested page, and returns a NoSQLPaginator:

var posts []Post
paginator, err := nosql.Query("mongo", "posts").
    Where("published", true).
    Latest().
    Paginate(ctx, &posts, 1, 20)    // page 1, 20 per page

// NoSQLPaginator fields
paginator.Data        // the posts slice
paginator.Total       // total matching count
paginator.PerPage     // 20
paginator.CurrentPage // 1
paginator.LastPage    // ceil(total / perPage)
paginator.HasMore()   // true if more pages exist

← NoSQL / MongoDB  |  Multiple DB Connections →