Use First() (or its alias Find()) to retrieve a single document matching your filter with a clean, type-safe API. Build filters with Where() and schema primitives to keep query logic expressive, composable, and production-friendly.
The most common pattern — query by ObjectID:
package main
import (
"context"
"errors"
"fmt"
"github.com/azayn-labs/mongorm"
"github.com/azayn-labs/mongorm/primitives"
"go.mongodb.org/mongo-driver/v2/bson"
"go.mongodb.org/mongo-driver/v2/mongo"
)
type ToDo struct {
ID *bson.ObjectID `bson:"_id,omitempty" mongorm:"primary"`
Text *string `bson:"text,omitempty"`
connectionString *string `mongorm:"mongodb://localhost:27017,connection:url"`
database *string `mongorm:"mydb,connection:database"`
collection *string `mongorm:"todos,connection:collection"`
}
type ToDoSchema struct {
ID *primitives.ObjectIDField
Text *primitives.StringField
}
var ToDoFields = mongorm.FieldsOf[ToDo, ToDoSchema]()
func main() {
ctx := context.Background()
targetID := bson.NewObjectID() // use a real ID in production
todo := &ToDo{}
orm := mongorm.New(todo)
orm.Where(ToDoFields.ID.Eq(targetID))
if err := orm.First(ctx); err != nil {
if errors.Is(err, mongo.ErrNoDocuments) {
fmt.Println("Document not found")
} else {
panic(err)
}
return
}
fmt.Printf("Found: %+v\n", todo)
}
After a successful call, the todo struct is populated with the data from the database.
todo := &ToDo{}
orm := mongorm.New(todo)
orm.Where(ToDoFields.Text.Eq("Buy groceries"))
if err := orm.First(ctx); err != nil {
panic(err)
}
todo := &ToDo{}
orm := mongorm.New(todo)
orm.Where(ToDoFields.Text.Reg("groceries$")) // matches text ending with "groceries"
if err := orm.First(ctx); err != nil {
panic(err)
}
Multiple Where() calls are combined with $and:
orm.Where(ToDoFields.Text.Reg("buy")).
Where(ToDoFields.CreatedAt.Gte(cutoff))
Find() is an alias for First(). Both retrieve one document and populate the schema pointer.
err := orm.Find(ctx) // same as orm.First(ctx)
err := orm.First(ctx)
WhereBy is a lower-level alternative that accepts any Field and a raw value:
orm.WhereBy(ToDoFields.Text, "Buy groceries")
To retrieve multiple documents, use FindAll() which returns a cursor. See Cursors for details.
Use Projection(...) together with FindOneAs[T, R] or FindAllAs[T, R] to decode partial documents into DTOs:
type ToDoPreview struct {
Text *string `bson:"text,omitempty"`
Count int64 `bson:"count,omitempty"`
}
model := mongorm.New(&ToDo{})
model.Where(ToDoFields.Text.Reg("^buy")).
Projection(bson.M{ToDoFields.Text.BSONName(): 1, ToDoFields.Count.BSONName(): 1})
one, err := mongorm.FindOneAs[ToDo, ToDoPreview](model, ctx)
if err != nil {
panic(err)
}
many, err := mongorm.FindAllAs[ToDo, ToDoPreview](model, ctx)
if err != nil {
panic(err)
}
fmt.Println(one, len(many))
Use Count() to get the number of documents matching current filters.
todo := &ToDo{}
orm := mongorm.New(todo)
count, err := orm.
Where(ToDoFields.Text.Reg("groceries")).
Count(ctx)
if err != nil {
panic(err)
}
fmt.Printf("Matched: %d\n", count)
Use Distinct() to return unique values for a field among matched documents.
todo := &ToDo{}
orm := mongorm.New(todo)
values, err := orm.
Where(ToDoFields.Text.Reg("^buy")).
Distinct(ctx, ToDoFields.Text)
if err != nil {
panic(err)
}
fmt.Printf("Distinct text values: %d\n", len(values))
Use typed helpers to avoid manual casting from []any:
texts, err := orm.DistinctStrings(ctx, ToDoFields.Text)
if err != nil {
panic(err)
}
counts, err := orm.DistinctInt64(ctx, ToDoFields.Count)
if err != nil {
panic(err)
}
flags, err := orm.DistinctBool(ctx, ToDoFields.Done)
if err != nil {
panic(err)
}
ids, err := orm.DistinctObjectIDs(ctx, ToDoFields.ID)
if err != nil {
panic(err)
}
times, err := orm.DistinctTimes(ctx, ToDoFields.CreatedAt)
if err != nil {
panic(err)
}
nums, err := orm.DistinctFloat64(ctx, ToDoFields.Count)
if err != nil {
panic(err)
}
Use DistinctFieldAs[T, V]() when you want typed results without a dedicated helper method:
texts, err := mongorm.DistinctFieldAs[ToDo, string](orm, ctx, ToDoFields.Text)
if err != nil {
panic(err)
}
ids, err := mongorm.DistinctFieldAs[ToDo, bson.ObjectID](orm, ctx, ToDoFields.ID)
if err != nil {
panic(err)
}
times, err := mongorm.DistinctFieldAs[ToDo, time.Time](orm, ctx, ToDoFields.CreatedAt)
if err != nil {
panic(err)
}
| Back to Documentation Index | README |