Query Expressions
Query expressions allow you to filter, sort, and paginate your data in ekoDB. This guide covers all operators, syntax patterns, and examples for both direct API usage and all client libraries.
Expression Structure
ekoDB uses a tagged union format for query expressions:
{
"type": "Condition" | "Logical",
"content": { ... }
}
Two Expression Types
- Condition - Single field comparison
- Logical - Combine multiple expressions (AND, OR, NOT)
Comparison Operators
All comparison operators follow this structure:
{
"type": "Condition",
"content": {
"field": "field_name",
"operator": "OperatorName",
"value": "comparison_value"
}
}
Available Operators
| Operator | Description | Aliases | Example Value |
|---|---|---|---|
Eq | Equals | Equal, Equals | "active", 25 |
Ne | Not equals | NotEqual, NotEquals | "deleted", 0 |
Gt | Greater than | GreaterThan | 18, 100.5 |
Gte | Greater than or equal | GreaterThanOrEqual | 18, 0 |
Lt | Less than | LessThan | 65, 1000 |
Lte | Less than or equal | LessThanOrEqual | 100, 999.99 |
In | Value in array | - | ["active", "pending"] |
NotIn | Value not in array | - | ["deleted", "archived"] |
String Operators
Special operators for string/text matching:
| Operator | Description | Case Sensitive | Example |
|---|---|---|---|
Contains | Substring match | Yes | "@gmail.com" |
StartsWith | Prefix match | Yes | "Dr. " |
EndsWith | Suffix match | Yes | ".com" |
All string operators are case-sensitive. To perform case-insensitive searches, normalize your data (e.g., lowercase) on insert.
Logical Operators
Combine multiple expressions with logical operators:
AND - All conditions must match
{
"type": "Logical",
"content": {
"operator": "And",
"expressions": [
{
"type": "Condition",
"content": {
"field": "age",
"operator": "Gte",
"value": 18
}
},
{
"type": "Condition",
"content": {
"field": "status",
"operator": "Eq",
"value": "active"
}
}
]
}
}
OR - At least one condition must match
{
"type": "Logical",
"content": {
"operator": "Or",
"expressions": [
{
"type": "Condition",
"content": {
"field": "role",
"operator": "Eq",
"value": "admin"
}
},
{
"type": "Condition",
"content": {
"field": "role",
"operator": "Eq",
"value": "moderator"
}
}
]
}
}
NOT - Negate a condition
{
"type": "Logical",
"content": {
"operator": "Not",
"expressions": [
{
"type": "Condition",
"content": {
"field": "status",
"operator": "Eq",
"value": "deleted"
}
}
]
}
}
Complex Nested Logic
You can nest logical operators for complex queries:
{
"type": "Logical",
"content": {
"operator": "And",
"expressions": [
{
"type": "Condition",
"content": {
"field": "age",
"operator": "Gte",
"value": 18
}
},
{
"type": "Logical",
"content": {
"operator": "Or",
"expressions": [
{
"type": "Condition",
"content": {
"field": "country",
"operator": "Eq",
"value": "US"
}
},
{
"type": "Condition",
"content": {
"field": "country",
"operator": "Eq",
"value": "CA"
}
}
]
}
}
]
}
}
This finds records where: age >= 18 AND (country = "US" OR country = "CA")
Query Options
Beyond filters, you can add sorting, pagination, and performance options:
{
"filter": { ... },
"sort": [
{
"field": "created_at",
"ascending": false
},
{
"field": "name",
"ascending": true
}
],
"limit": 10,
"skip": 20,
"bypass_cache": false,
"bypass_ripple": true
}
Options Reference
| Option | Type | Description |
|---|---|---|
filter | QueryExpression | Filter condition (see above) |
sort | Array | Sort by one or more fields |
limit | Integer | Max results to return |
skip | Integer | Results to skip (pagination) |
bypass_cache | Boolean | Skip cache lookup |
bypass_ripple | Boolean | Don't propagate to ripple peers |
Usage Examples
For practical examples of using query expressions:
- Direct API - See Basic Operations - Query Examples
- Client Libraries - See Querying with Filters
Common Query Patterns
Find All Active Records
{
"filter": {
"type": "Condition",
"content": {
"field": "status",
"operator": "Eq",
"value": "active"
}
}
}
Range Query (Between Values)
{
"filter": {
"type": "Logical",
"content": {
"operator": "And",
"expressions": [
{
"type": "Condition",
"content": {
"field": "price",
"operator": "Gte",
"value": 10.00
}
},
{
"type": "Condition",
"content": {
"field": "price",
"operator": "Lte",
"value": 100.00
}
}
]
}
}
}
Exclude Values (NOT IN)
{
"filter": {
"type": "Condition",
"content": {
"field": "status",
"operator": "NotIn",
"value": ["deleted", "archived", "spam"]
}
}
}
Search Multiple Fields (OR)
{
"filter": {
"type": "Logical",
"content": {
"operator": "Or",
"expressions": [
{
"type": "Condition",
"content": {
"field": "title",
"operator": "Contains",
"value": "urgent"
}
},
{
"type": "Condition",
"content": {
"field": "description",
"operator": "Contains",
"value": "urgent"
}
}
]
}
}
}
Complex Business Logic
Find premium users who are either:
- Over 30 years old, OR
- Have made more than 10 purchases
{
"filter": {
"type": "Logical",
"content": {
"operator": "And",
"expressions": [
{
"type": "Condition",
"content": {
"field": "tier",
"operator": "Eq",
"value": "premium"
}
},
{
"type": "Logical",
"content": {
"operator": "Or",
"expressions": [
{
"type": "Condition",
"content": {
"field": "age",
"operator": "Gt",
"value": 30
}
},
{
"type": "Condition",
"content": {
"field": "purchase_count",
"operator": "Gt",
"value": 10
}
}
]
}
}
]
}
}
}
Performance Tips
Use Indexes
First, generate an access token using your API key:
curl -X POST https://{EKODB_API_URL}/api/auth/token \
-H "Content-Type: application/json" \
-d '{"api_key": "YOUR_API_KEY"}'
Response:
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
Create indexes on fields you query frequently:
curl -X POST https://{EKODB_API_URL}/api/indexes/users \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"field": "status",
"index_type": "hash"
}'
See Indexes Documentation for more details.
Limit Results
Always use limit to prevent loading excessive data:
{
"filter": { ... },
"limit": 100
}
Bypass Cache for Fresh Data
When you need the absolute latest data:
{
"filter": { ... },
"bypass_cache": true
}
Use Specific Fields
Only select fields you need (reduces bandwidth):
{
"filter": { ... },
"select_fields": ["id", "name", "email"]
}
Troubleshooting
400 Bad Request - Invalid Filter Format
❌ Wrong:
{
"filter": {
"field": "status",
"operator": "Eq",
"value": "active"
}
}
✅ Correct:
{
"filter": {
"type": "Condition",
"content": {
"field": "status",
"operator": "Eq",
"value": "active"
}
}
}
Missing type and content wrapper!
400 Bad Request - Unknown Operator
❌ Wrong:
{
"operator": "equals" // lowercase
}
✅ Correct:
{
"operator": "Eq" // PascalCase
}
Operators are case-sensitive and use PascalCase.
Empty Results When Data Exists
- Check if field names are correct (case-sensitive)
- Verify value types match (string vs number)
- For string matching, remember it's case-sensitive
Next Steps
- Basic Operations - Complete CRUD API reference
- Indexes - Speed up your queries
- Client Libraries - Type-safe query building
- Batch Operations - Query multiple records efficiently
Need Help?
- 📖 Client Library Examples: GitHub Examples (includes both client library and direct HTTP examples)
- 🐛 Issues: app.ekodb.io/support
- 💬 Support: support@ekodb.io