Query Language
Powerful query syntax for filtering and finding documents
Overview
jasonisnthappy includes a custom query language for filtering documents. The query language supports comparison operators, logical operators, field existence checks, and array operations. All queries are evaluated efficiently using the database's indexing system.
Comparison Operators
Use comparison operators to filter documents based on field values.
Greater Than (>)
age > 30
Matches documents where the age field is greater than 30.
Greater Than or Equal (>=)
age >= 30
Matches documents where the age field is greater than or equal to 30.
Less Than (<)
age < 30
Matches documents where the age field is less than 30.
Less Than or Equal (<=)
age <= 30
Matches documents where the age field is less than or equal to 30.
Equals (is)
name is "Alice"
status is true
count is 42
value is null
Matches documents where the field exactly equals the specified value. Supports strings, numbers, booleans, and null.
Not Equals (is not)
name is not "Bob"
Matches documents where the field does not equal the specified value.
Logical Operators
Combine multiple conditions using logical operators.
AND
age > 30 and city is "NYC"
Both conditions must be true for the document to match.
OR
age < 18 or age > 65
At least one condition must be true for the document to match.
NOT
not age > 30
Negates a condition. The document matches if the condition is false.
Parentheses for Grouping
(age < 18 or age > 65) and status is "active"
Use parentheses to control evaluation order and create complex logic.
Field Operators
Exists
email exists
Matches documents that have the specified field (field is not null).
Not Exists
email not exists
Matches documents that do not have the specified field (field is null or missing).
Boolean Shorthand
active
Shorthand for active is true. Matches documents where the field is true.
Array Operators
Query documents with array fields using specialized array operators.
Has
tags has "javascript"
Matches documents where the tags array contains the value "javascript".
Has Any
tags has any ["javascript", "typescript", "rust"]
Matches documents where the tags array contains at least one of the specified values.
Has All
tags has all ["javascript", "typescript"]
Matches documents where the tags array contains all of the specified values.
Nested Fields
Access nested object fields using dot notation.
user.address.city is "NYC"
user.profile.age > 30
settings.notifications.email is true
Use dots to traverse nested objects and query deeply nested fields.
Query Examples
Simple Queries
// Find users older than 30
age > 30
// Find active users
status is "active"
// Find users with email addresses
email exists
Complex Queries
// Find active users in NYC older than 25
age > 25 and city is "NYC" and status is "active"
// Find users who are either minors or seniors
age < 18 or age > 65
// Find users with specific tags
tags has any ["premium", "verified"]
Nested Field Queries
// Find users in NYC with verified profiles
user.address.city is "NYC" and user.profile.verified is true
// Find users with high engagement scores
metrics.engagement.score > 80 and metrics.active is true
Combined Queries
// Find premium users in specific cities who are active
(city is "NYC" or city is "SF") and subscription is "premium" and status is "active"
// Find users who don't have certain attributes
not (tags has "spam") and not (status is "banned")
// Complex filtering with multiple conditions
age >= 18 and age <= 65 and (income > 50000 or education is "graduate") and employment is "employed"
Usage in Code
use jasonisnthappy::Database;
fn main() -> jasonisnthappy::Result<()> {
let db = Database::open("my.db")?;
let collection = db.collection("users");
// Find with query
let results = collection.find("age > 30 and city is \"NYC\"")?;
// Count matching documents
let count = collection.count_with_query("status is \"active\"")?;
// Find one document
let user = collection.find_one("email is \"alice@example.com\"")?;
Ok(())
}
from jasonisnthappy import Database
with Database.open("my.db") as db:
collection = db.collection("users")
# Find with query
results = collection.find('age > 30 and city is "NYC"')
# Count matching documents
count = collection.count_with_query('status is "active"')
# Find one document
user = collection.find_one('email is "alice@example.com"')
const { Database } = require('jasonisnthappy');
const db = Database.open('my.db');
const collection = db.collection('users');
// Find with query
const results = collection.find('age > 30 and city is "NYC"');
// Count matching documents
const count = collection.countWithQuery('status is "active"');
// Find one document
const user = collection.findOne('email is "alice@example.com"');
db.close();
package main
import (
"github.com/sohzm/jasonisnthappy-go"
)
func main() {
db, _ := jasonisnthappy.Open("my.db")
defer db.Close()
collection, _ := db.Collection("users")
// Find with query
results, _ := collection.Find("age > 30 and city is \"NYC\"")
// Count matching documents
count, _ := collection.CountWithQuery("status is \"active\"")
// Find one document
user, _ := collection.FindOne("email is \"alice@example.com\"")
}
Performance Tips
- Use Indexes: Create indexes on fields used in queries for faster lookups
- Specific Queries: More specific queries are generally faster than broad ones
- Compound Indexes: Use compound indexes for queries with multiple field conditions
- Avoid NOT: When possible, express conditions positively rather than using NOT