Comprehensive documentation for noneDB's Query Builder API.
Version: 3.1.0
- Quick Start
- Query Builder Basics
- Comparison Operators
- Filter Methods
- Sorting & Pagination
- Aggregation
- Joins
- Grouping & Having
- Spatial Queries
- Terminal Methods
- Real-World Examples
- Performance Tips
$db = new noneDB();
// Simple query
$users = $db->query("users")
->where(['active' => true])
->sort('created_at', 'desc')
->limit(10)
->get();
// Advanced query with operators
$products = $db->query("products")
->where([
'price' => ['$gte' => 100, '$lte' => 500],
'category' => ['$in' => ['electronics', 'gadgets']],
'stock' => ['$gt' => 0]
])
->sort('rating', 'desc')
->get();// Get query builder instance
$query = $db->query("database_name");
// Chain methods and execute
$results = $query
->where(['field' => 'value'])
->get();All filter and modifier methods return $this, allowing fluent chaining:
$results = $db->query("users")
->where(['status' => 'active'])
->whereIn('role', ['admin', 'moderator'])
->sort('name', 'asc')
->limit(20)
->offset(0)
->get();noneDB supports MongoDB-style comparison operators in where() clauses.
| Operator | Description | Example |
|---|---|---|
$gt |
Greater than | ['age' => ['$gt' => 18]] |
$gte |
Greater than or equal | ['price' => ['$gte' => 100]] |
$lt |
Less than | ['stock' => ['$lt' => 10]] |
$lte |
Less than or equal | ['rating' => ['$lte' => 5]] |
$eq |
Equal (explicit) | ['status' => ['$eq' => 'active']] |
$ne |
Not equal | ['role' => ['$ne' => 'guest']] |
$in |
Value in array | ['category' => ['$in' => ['a', 'b']]] |
$nin |
Value not in array | ['tag' => ['$nin' => ['spam']]] |
$exists |
Field exists/not exists | ['email' => ['$exists' => true]] |
$like |
Pattern matching | ['name' => ['$like' => 'John']] |
$regex |
Regular expression | ['email' => ['$regex' => '@gmail.com$']] |
$contains |
Array/string contains | ['tags' => ['$contains' => 'featured']] |
// Find adults
$adults = $db->query("users")
->where(['age' => ['$gte' => 18]])
->get();
// Find products under $100
$affordable = $db->query("products")
->where(['price' => ['$lt' => 100]])
->get();
// Range query (between 18 and 65)
$workingAge = $db->query("users")
->where(['age' => ['$gte' => 18, '$lte' => 65]])
->get();// Not equal
$nonAdmins = $db->query("users")
->where(['role' => ['$ne' => 'admin']])
->get();
// Explicit equality (same as simple value)
$active = $db->query("users")
->where(['status' => ['$eq' => 'active']])
->get();// Find users in specific roles
$staff = $db->query("users")
->where(['role' => ['$in' => ['admin', 'moderator', 'editor']]])
->get();
// Exclude certain categories
$products = $db->query("products")
->where(['category' => ['$nin' => ['discontinued', 'draft']]])
->get();// Find records with email field
$withEmail = $db->query("users")
->where(['email' => ['$exists' => true]])
->get();
// Find records without phone field
$noPhone = $db->query("users")
->where(['phone' => ['$exists' => false]])
->get();// Contains (case-insensitive)
$johns = $db->query("users")
->where(['name' => ['$like' => 'john']])
->get();
// Starts with (use ^)
$mNames = $db->query("users")
->where(['name' => ['$like' => '^M']])
->get();
// Ends with (use $)
$gmails = $db->query("users")
->where(['email' => ['$like' => 'gmail.com$']])
->get();
// Regular expression
$validEmails = $db->query("users")
->where(['email' => ['$regex' => '^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$']])
->get();// Check if array field contains value
$featuredProducts = $db->query("products")
->where(['tags' => ['$contains' => 'featured']])
->get();
// Check if string field contains substring
$techNews = $db->query("articles")
->where(['title' => ['$contains' => 'technology']])
->get();// Multiple operators on same field
$midRange = $db->query("products")
->where([
'price' => ['$gte' => 50, '$lte' => 200],
'rating' => ['$gte' => 4.0]
])
->get();
// Mix operators with simple equality
$activeAdmins = $db->query("users")
->where([
'role' => 'admin', // Simple equality
'status' => 'active', // Simple equality
'login_count' => ['$gt' => 100], // Operator
'last_login' => ['$exists' => true] // Operator
])
->get();Primary filter method. Applies AND logic across all conditions.
// Simple equality
$db->query("users")->where(['name' => 'John', 'active' => true]);
// With operators
$db->query("users")->where([
'age' => ['$gte' => 18],
'country' => ['$in' => ['US', 'UK', 'CA']]
]);Adds OR conditions to the query.
// Users who are admins OR have high reputation
$db->query("users")
->where(['role' => 'admin'])
->orWhere(['reputation' => ['$gte' => 1000]])
->get();
// Multiple OR conditions
$db->query("products")
->where(['category' => 'electronics'])
->orWhere(['featured' => true])
->orWhere(['discount' => ['$gt' => 50]])
->get();Filter by array membership.
// Users in specific departments
$db->query("users")
->whereIn('department', ['engineering', 'design', 'product'])
->get();
// Products NOT in these categories
$db->query("products")
->whereNotIn('category', ['archived', 'deleted'])
->get();Exclude records matching conditions.
// All users except guests
$db->query("users")
->whereNot(['role' => 'guest'])
->get();Pattern matching on string fields.
// Names starting with 'A'
$db->query("users")->like('name', '^A')->get();
// Names ending with 'son'
$db->query("users")->like('name', 'son$')->get();
// Names containing 'john' (case-insensitive)
$db->query("users")->like('name', 'john')->get();
// Exclude spam titles
$db->query("posts")->notLike('title', 'SPAM')->get();Range filtering (inclusive).
// Products priced $50-$200
$db->query("products")
->between('price', 50, 200)
->get();
// Ages outside 18-65 range
$db->query("users")
->notBetween('age', 18, 65)
->get();Full-text search across fields.
// Search in all fields
$db->query("articles")
->search('php tutorial')
->get();
// Search in specific fields
$db->query("articles")
->search('php tutorial', ['title', 'content', 'tags'])
->get();Sort results by field.
// Ascending (default)
$db->query("users")->sort('name')->get();
$db->query("users")->sort('name', 'asc')->get();
// Descending
$db->query("products")->sort('price', 'desc')->get();
// Sort by distance (spatial queries)
$db->query("locations")
->withinDistance('coords', $lon, $lat, 10)
->withDistance('coords', $lon, $lat)
->sort('_distance', 'asc')
->get();Paginate results.
// First 10 records
$db->query("products")->limit(10)->get();
// Page 2 (records 11-20)
$db->query("products")->limit(10)->offset(10)->get();
// Helper function for pagination
function paginate($db, $dbname, $page, $perPage = 20) {
return $db->query($dbname)
->limit($perPage)
->offset(($page - 1) * $perPage)
->get();
}Count matching records.
$totalUsers = $db->query("users")->count();
$activeUsers = $db->query("users")
->where(['active' => true])
->count();Numeric aggregations.
// Total revenue
$revenue = $db->query("orders")
->where(['status' => 'completed'])
->sum('total');
// Average rating
$avgRating = $db->query("products")
->where(['category' => 'electronics'])
->avg('rating');
// Price range
$minPrice = $db->query("products")->min('price');
$maxPrice = $db->query("products")->max('price');Combine data from multiple databases.
// Join orders with users
$ordersWithUsers = $db->query("orders")
->join("users", "user_id", "key") // orders.user_id = users.key
->get();
// Result includes user data in _joined field
foreach ($ordersWithUsers as $order) {
echo $order['_joined']['name']; // User's name
}$data = $db->query("order_items")
->join("orders", "order_id", "key")
->join("products", "product_id", "key")
->get();Group results by field value.
// Group orders by status
$ordersByStatus = $db->query("orders")
->groupBy('status')
->get();
// Returns: [
// 'pending' => [...orders],
// 'completed' => [...orders],
// 'cancelled' => [...orders]
// ]Filter groups by aggregate conditions.
// Customers with more than 5 orders
$frequentCustomers = $db->query("orders")
->groupBy('customer_id')
->having('count', '>', 5)
->get();
// Categories with average rating >= 4
$goodCategories = $db->query("products")
->groupBy('category')
->having('avg', '>=', 4, 'rating')
->get();noneDB supports geospatial queries with R-tree indexing.
// Create index on location field (required before spatial queries)
$db->createSpatialIndex("restaurants", "location");
// Check if index exists
$db->hasSpatialIndex("restaurants", "location"); // true/false
// List all spatial indexes
$db->getSpatialIndexes("restaurants"); // ['location']
// Drop spatial index
$db->dropSpatialIndex("restaurants", "location");// Point
$point = [
'type' => 'Point',
'coordinates' => [28.9784, 41.0082] // [longitude, latitude]
];
// LineString
$line = [
'type' => 'LineString',
'coordinates' => [
[28.97, 41.00],
[28.98, 41.01],
[28.99, 41.02]
]
];
// Polygon
$polygon = [
'type' => 'Polygon',
'coordinates' => [[
[28.97, 41.00],
[29.00, 41.00],
[29.00, 41.03],
[28.97, 41.03],
[28.97, 41.00] // First point repeated to close
]]
];Find records within radius of a point.
// Direct method
$nearby = $db->withinDistance("restaurants", "location",
28.9784, // longitude
41.0082, // latitude
5 // radius in km
);
// Query builder
$nearby = $db->query("restaurants")
->withinDistance('location', 28.9784, 41.0082, 5)
->where(['open_now' => true])
->get();Find records within bounding box.
// Direct method
$inArea = $db->withinBBox("restaurants", "location",
28.97, 41.00, // minLon, minLat
29.00, 41.03 // maxLon, maxLat
);
// Query builder
$inArea = $db->query("restaurants")
->withinBBox('location', 28.97, 41.00, 29.00, 41.03)
->where(['category' => 'cafe'])
->get();Find K nearest records.
// Direct method
$closest = $db->nearest("restaurants", "location",
28.9784, 41.0082, // reference point
5 // number of results
);
// Query builder with distance
$closest = $db->query("restaurants")
->nearest('location', 28.9784, 41.0082, 10)
->where(['rating' => ['$gte' => 4.0]])
->withDistance('location', 28.9784, 41.0082)
->sort('_distance', 'asc')
->limit(5)
->get();Find records within polygon boundary.
$polygon = [
'type' => 'Polygon',
'coordinates' => [[
[28.97, 41.00],
[29.00, 41.00],
[29.00, 41.03],
[28.97, 41.03],
[28.97, 41.00]
]]
];
// Direct method
$inPolygon = $db->withinPolygon("restaurants", "location", $polygon);
// Query builder
$inPolygon = $db->query("restaurants")
->withinPolygon('location', $polygon)
->where(['price_range' => ['$lte' => 3]])
->get();Add calculated distance to results.
$results = $db->query("restaurants")
->withinDistance('location', $userLon, $userLat, 10)
->withDistance('location', $userLon, $userLat)
->sort('_distance', 'asc')
->get();
foreach ($results as $r) {
echo "{$r['name']}: {$r['_distance']} km away\n";
}// Food delivery app: find nearby open restaurants with delivery
$restaurants = $db->query("restaurants")
->withinDistance('location', $userLon, $userLat, 5)
->where([
'open_now' => true,
'delivery' => true,
'rating' => ['$gte' => 4.0],
'price_range' => ['$lte' => 3],
'cuisine' => ['$in' => ['turkish', 'italian', 'chinese']]
])
->withDistance('location', $userLon, $userLat)
->sort('rating', 'desc')
->limit(20)
->get();Terminal methods execute the query and return results.
Returns all matching records as array.
$results = $db->query("users")->where(['active' => true])->get();Returns first matching record or null.
$user = $db->query("users")->where(['email' => 'john@example.com'])->first();Returns number of matching records.
$count = $db->query("users")->where(['role' => 'admin'])->count();Returns boolean indicating if any records match.
$hasAdmins = $db->query("users")->where(['role' => 'admin'])->exists();Updates matching records and returns result.
$result = $db->query("users")
->where(['status' => 'inactive'])
->update(['status' => 'archived']);
// Returns: ['n' => 5, 'keys' => [1, 3, 7, 12, 15]]Deletes matching records and returns result.
$result = $db->query("logs")
->where(['created_at' => ['$lt' => strtotime('-30 days')]])
->delete();
// Returns: ['n' => 100, 'keys' => [...]]$products = $db->query("products")
->where([
'category' => ['$in' => ['electronics', 'computers']],
'price' => ['$gte' => 100, '$lte' => 1000],
'stock' => ['$gt' => 0],
'rating' => ['$gte' => 4.0]
])
->whereNot(['status' => 'discontinued'])
->search($searchTerm, ['name', 'description'])
->sort('rating', 'desc')
->limit(20)
->offset($page * 20)
->get();$user = $db->query("users")
->where([
'email' => $email,
'password_hash' => $passwordHash,
'status' => 'active',
'email_verified' => true
])
->first();// Orders by status
$orderStats = $db->query("orders")
->where(['created_at' => ['$gte' => $startDate, '$lte' => $endDate]])
->groupBy('status')
->get();
// Revenue by category
$categoryRevenue = [];
foreach ($db->query("orders")->where(['status' => 'completed'])->get() as $order) {
$cat = $order['category'];
$categoryRevenue[$cat] = ($categoryRevenue[$cat] ?? 0) + $order['total'];
}// Find nearby services with filters
$services = $db->query("services")
->withinDistance('location', $userLon, $userLat, 10)
->where([
'available' => true,
'rating' => ['$gte' => 4.0],
'price_per_hour' => ['$lte' => $maxBudget],
'category' => ['$in' => $selectedCategories]
])
->withDistance('location', $userLon, $userLat)
->sort('_distance', 'asc')
->limit(10)
->get();// Published articles with tags
$articles = $db->query("articles")
->where([
'status' => 'published',
'published_at' => ['$lte' => time()],
'tags' => ['$contains' => 'featured']
])
->sort('published_at', 'desc')
->limit(10)
->get();
// Search with category filter
$results = $db->query("articles")
->where(['category' => ['$in' => ['tech', 'science']]])
->search($query, ['title', 'content', 'excerpt'])
->sort('published_at', 'desc')
->get();// Create field index for frequently queried fields
$db->createFieldIndex("users", "email");
$db->createFieldIndex("products", "category");
// Create spatial index for location queries
$db->createSpatialIndex("locations", "coords");// Always limit when you don't need all results
$db->query("logs")->limit(100)->get();
// Use first() instead of get()[0]
$db->query("users")->where(['id' => $id])->first();// Only fetch name and email
$db->query("users")->select(['name', 'email'])->get();
// Exclude large fields
$db->query("articles")->except(['content', 'raw_html'])->get();// Good: Filter with where() first
$db->query("orders")
->where(['status' => 'completed']) // Filter first
->between('total', 100, 500) // Then range
->sort('created_at', 'desc')
->get();// Always create spatial index before queries
$db->createSpatialIndex("restaurants", "location");
// Then queries are O(log n) instead of O(n)
$db->withinDistance("restaurants", "location", $lon, $lat, 5);// Batch insert instead of individual inserts
$db->insert("logs", $arrayOf1000Records); // Single operation
// Batch update
$db->query("orders")
->where(['status' => 'pending', 'created_at' => ['$lt' => $oldDate]])
->update(['status' => 'expired']);['$gt' => value] // Greater than
['$gte' => value] // Greater than or equal
['$lt' => value] // Less than
['$lte' => value] // Less than or equal
['$eq' => value] // Equal (explicit)
['$ne' => value] // Not equal
['$in' => [a,b,c]] // In array
['$nin' => [a,b,c]] // Not in array
['$exists' => bool] // Field exists
['$like' => pattern] // Pattern match (^start, end$)
['$regex' => pattern] // Regex match
['$contains' => val] // Array/string contains->withinDistance($field, $lon, $lat, $km)
->withinBBox($field, $minLon, $minLat, $maxLon, $maxLat)
->nearest($field, $lon, $lat, $k)
->withinPolygon($field, $polygon)
->withDistance($field, $lon, $lat)->where([...])
->orWhere([...])
->whereIn($field, [...])
->whereNotIn($field, [...])
->whereNot([...])
->like($field, $pattern)
->notLike($field, $pattern)
->between($field, $min, $max)
->notBetween($field, $min, $max)
->search($term, $fields)->sort($field, 'asc'|'desc')
->limit($count)
->offset($count)
->select([...])
->except([...])
->join($db, $localKey, $foreignKey)
->groupBy($field)
->having($aggregate, $operator, $value)->get() // Array of records
->first() // Single record or null
->count() // Integer count
->exists() // Boolean
->sum($field) // Numeric sum
->avg($field) // Numeric average
->min($field) // Minimum value
->max($field) // Maximum value
->update([...])// Update result
->delete() // Delete result| Version | Changes |
|---|---|
| 3.1.0 | Added comparison operators ($gt, $gte, $lt, $lte, $ne, $eq, $in, $nin, $exists, $like, $regex, $contains) |
| 3.1.0 | Added spatial indexing with R-tree (withinDistance, withinBBox, nearest, withinPolygon) |
| 3.1.0 | Added withDistance() for distance calculations |
| 3.0.0 | JSONL storage with O(1) key lookup |
| 3.0.0 | Single-pass filtering optimization |
| 3.0.0 | Static cache sharing across instances |