Typed Search Expressions
The typed client supports Django-style query expressions on SearchParams fields.
String and integer fields in every *SearchParams struct are typed as client.StrField or
client.IntField instead of plain string / int64. This allows you to pass either an
exact value or a rich lookup expression without falling back to RawData.
All expression helpers are exported directly from the top-level client package — no extra
import needed.
Quick Reference
| Factory | Type | Generated query parameter |
|---|---|---|
expr.Str("foo") |
StrField |
name=foo |
expr.Str.Exact("foo") |
StrField |
name=foo |
expr.Str.Contains("foo") |
StrField |
name__contains=foo |
expr.Str.IContains("foo") |
StrField |
name__icontains=foo |
expr.Str.StartsWith("foo") |
StrField |
name__startswith=foo |
expr.Str.EndsWith("foo") |
StrField |
name__endswith=foo |
expr.Str.Regex( `^sys\d+` ) |
StrField |
name__regex=^sys\d+ |
expr.Str.IRegex( `^sys\d+` ) |
StrField |
name__iregex=^sys\d+ |
expr.Str.In("a", "b") |
StrField |
name__in=a,b |
expr.Str.NotContains("foo") |
StrField |
name__not_contains=foo |
expr.Str.NotIn("a", "b") |
StrField |
name__not_in=a,b |
expr.Int(42) |
IntField |
uid=42 |
expr.Int.Exact(42) |
IntField |
uid=42 |
expr.Int.GT(100) |
IntField |
uid__gt=100 |
expr.Int.GTE(100) |
IntField |
uid__gte=100 |
expr.Int.LT(100) |
IntField |
uid__lt=100 |
expr.Int.LTE(100) |
IntField |
uid__lte=100 |
expr.Int.In(1, 2, 3) |
IntField |
uid__in=1,2,3 |
expr.Int.NotGTE(9999) |
IntField |
uid__not_gte=9999 |
Negated variants exist for all expressions:
NotExact,NotContains,NotStartsWith, etc.
Exact Match
Call expr.Str / expr.Int directly for an exact-match filter:
// GET /users/?name=admin
user, err := rest.Users.Get(&typed.UserSearchParams{
Name: expr.Str("admin"),
})
// GET /users/?uid=9999
user, err := rest.Users.Get(&typed.UserSearchParams{
Uid: expr.Int(9999),
})
String Expressions
// GET /snapshots/?name__startswith=go-client
snapshots, err := rest.Snapshots.List(&typed.SnapshotSearchParams{
Name: expr.Str.StartsWith("go-client"),
})
// GET /views/?path__contains=production
views, err := rest.Views.List(&typed.ViewSearchParams{
Path: expr.Str.Contains("production"),
})
// GET /users/?name__in=alice,bob,carol
users, err := rest.Users.List(&typed.UserSearchParams{
Name: expr.Str.In("alice", "bob", "carol"),
})
// GET /protectedpaths/?name__endswith=b816a408a6
path, err := rest.ProtectedPaths.Get(&typed.ProtectedPathSearchParams{
Name: expr.Str.EndsWith("b816a408a6"),
})
// GET /users/?name__icontains=admin (case-insensitive)
users, err := rest.Users.List(&typed.UserSearchParams{
Name: expr.Str.IContains("admin"),
})
// GET /views/?name__regex=^prod-\d+
views, err := rest.Views.List(&typed.ViewSearchParams{
Name: expr.Str.Regex(`^prod-\d+`),
})
Integer Expressions
// GET /users/?uid__gt=1000
users, err := rest.Users.List(&typed.UserSearchParams{
Uid: expr.Int.GT(1000),
})
// GET /users/?uid__gte=500&uid__lte=999 (range)
users, err := rest.Users.List(&typed.UserSearchParams{
Uid: expr.Int.GTE(500),
// combine multiple fields freely
})
// GET /users/?uid__in=1,2,3 (primary-key lookup)
users, err := rest.Users.List(&typed.UserSearchParams{
Uid: expr.Int.In(1, 2, 3),
})
// GET /quotas/?tenant_id__not_in=5,6
quotas, err := rest.Quotas.List(&typed.QuotaSearchParams{
TenantId: expr.Int.NotIn(5, 6),
})
Combining Multiple Fields
All SearchParams fields are independent — set as many as needed:
// GET /vippools/?name__startswith=prod&tenant_id__gte=10
pools, err := rest.VipPools.List(&typed.VipPoolSearchParams{
Name: expr.Str.StartsWith("prod"),
TenantId: expr.Int.GTE(10),
})
Negation
Every expression has a Not* counterpart:
// GET /users/?name__not_contains=test
users, err := rest.Users.List(&typed.UserSearchParams{
Name: expr.Str.NotContains("test"),
})
// GET /users/?uid__not_in=0,1
users, err := rest.Users.List(&typed.UserSearchParams{
Uid: expr.Int.NotIn(0, 1),
})
RawData Fallback
If a backend filter has no corresponding typed field (e.g., a newly added parameter not yet
regenerated), use RawData:
users, err := rest.Users.List(&typed.UserSearchParams{
Name: expr.Str.StartsWith("svc"),
RawData: client.Params{"some_new_filter": "value"},
})
Typed fields and RawData are merged before the request is sent.