Operators Guide (v5.0.0)
This guide covers all the MongoDB-style operators available in @mcabreradev/filter v5.0.0.
Table of Contents
- Comparison Operators
- Array Operators
- String Operators
- Logical Operators
- Combining Operators
- Real-World Examples
Comparison Operators
$gt - Greater Than
Returns items where the property value is greater than the specified value.
import { filter } from '@mcabreradev/filter';
const products = [
{ name: 'Laptop', price: 1200 },
{ name: 'Mouse', price: 25 },
{ name: 'Monitor', price: 450 }
];
filter(products, { price: { $gt: 100 } });
// → Returns: Laptop ($1200) and Monitor ($450)$gte - Greater Than or Equal
Returns items where the property value is greater than or equal to the specified value.
filter(products, { price: { $gte: 450 } });
// → Returns: Laptop ($1200) and Monitor ($450)$lt - Less Than
Returns items where the property value is less than the specified value.
filter(products, { price: { $lt: 500 } });
// → Returns: Mouse ($25) and Monitor ($450)$lte - Less Than or Equal
Returns items where the property value is less than or equal to the specified value.
filter(products, { price: { $lte: 450 } });
// → Returns: Mouse ($25) and Monitor ($450)$eq - Equal
Returns items where the property value equals the specified value.
filter(products, { price: { $eq: 450 } });
// → Returns: Monitor ($450)$ne - Not Equal
Returns items where the property value does not equal the specified value.
filter(products, { price: { $ne: 25 } });
// → Returns: Laptop ($1200) and Monitor ($450)Date Comparisons
All comparison operators work with dates:
const orders = [
{ id: 1, date: new Date('2025-01-15') },
{ id: 2, date: new Date('2025-02-20') },
{ id: 3, date: new Date('2025-03-10') }
];
filter(orders, {
date: {
$gte: new Date('2025-02-01'),
$lte: new Date('2025-03-31')
}
});
// → Returns: orders 2 and 3Range Queries
Combine $gte and $lte (or $gt and $lt) to create range queries:
filter(products, {
price: { $gte: 100, $lte: 500 }
});
// → Returns products with price between $100 and $500 (inclusive)Array Operators
$in - In Array
Returns items where the property value is in the specified array.
const products = [
{ id: 1, category: 'Electronics' },
{ id: 2, category: 'Furniture' },
{ id: 3, category: 'Books' }
];
filter(products, {
category: { $in: ['Electronics', 'Books'] }
});
// → Returns: products 1 and 3$nin - Not In Array
Returns items where the property value is not in the specified array.
filter(products, {
category: { $nin: ['Furniture'] }
});
// → Returns: products 1 and 3$contains - Array Contains
Returns items where the array property contains the specified value.
const products = [
{ name: 'Laptop', tags: ['computer', 'portable'] },
{ name: 'Mouse', tags: ['computer', 'accessory'] },
{ name: 'Desk', tags: ['office', 'large'] }
];
filter(products, {
tags: { $contains: 'computer' }
});
// → Returns: Laptop and Mouse$size - Array Size
Returns items where the array property has the specified length.
filter(products, {
tags: { $size: 2 }
});
// → Returns all products (all have exactly 2 tags)Array Syntax - Syntactic Sugar for $in
You can use array values directly as a shorthand for the $in operator. This provides a cleaner, more intuitive syntax for OR logic.
Basic Usage
const users = [
{ name: 'Alice', city: 'Berlin', age: 30 },
{ name: 'Bob', city: 'London', age: 25 },
{ name: 'Charlie', city: 'Berlin', age: 35 },
{ name: 'David', city: 'Paris', age: 30 }
];
// Array syntax (syntactic sugar)
filter(users, { city: ['Berlin', 'London'] });
// → Returns: Alice, Bob, Charlie
// Equivalent explicit $in operator
filter(users, { city: { $in: ['Berlin', 'London'] } });
// → Returns: Alice, Bob, Charlie (identical result)How It Works
When you provide an array as a property value (without an explicit operator), the filter automatically applies OR logic to match any value in the array:
// These are functionally equivalent:
{ city: ['Berlin', 'London', 'Paris'] }
{ city: { $in: ['Berlin', 'London', 'Paris'] } }
// Both mean: city === 'Berlin' OR city === 'London' OR city === 'Paris'Combining with AND Logic
Array syntax (OR logic) combines with other properties using AND logic:
// Find users in Berlin OR London AND age 30
filter(users, {
city: ['Berlin', 'London'],
age: 30
});
// → Returns: Alice (Berlin, age 30)
// Logic: (city === 'Berlin' OR city === 'London') AND age === 30Multiple Array Properties
You can use arrays on multiple properties - each applies OR logic independently:
// Find users in (Berlin OR Paris) AND age (30 OR 35)
filter(users, {
city: ['Berlin', 'Paris'],
age: [30, 35]
});
// → Returns: Alice (Berlin, 30), Charlie (Berlin, 35), David (Paris, 30)
// Logic: (city === 'Berlin' OR city === 'Paris') AND (age === 30 OR age === 35)Wildcard Support
Array syntax supports wildcards within array values:
// Match cities starting with 'B' or ending with 'is'
filter(users, { city: ['B%', '%is'] });
// → Returns: Bob (London matches 'B%'), David (Paris matches '%is')
// Underscore wildcard
filter(users, { city: ['_erlin', 'L_ndon'] });
// → Returns: Alice (Berlin), Bob (London)Works with All Types
Array syntax works with strings, numbers, booleans, and other primitive types:
// Numbers
filter(users, { age: [25, 30, 35] });
// → Returns users aged 25, 30, or 35
// Strings
filter(users, { name: ['Alice', 'Bob'] });
// → Returns Alice and Bob
// Booleans
filter(products, { inStock: [true] });
// → Returns products in stockEdge Cases
// Empty array matches nothing
filter(users, { city: [] });
// → Returns: []
// Single-element array
filter(users, { city: ['Berlin'] });
// → Returns: Alice, Charlie (same as { city: 'Berlin' })Important: Explicit Operators Take Precedence
When you use an explicit operator, the array syntax does NOT apply:
// Array syntax - applies OR logic
filter(users, { city: ['Berlin', 'London'] });
// → Matches: Berlin OR London
// Explicit $in operator - uses operator logic
filter(users, { city: { $in: ['Berlin', 'London'] } });
// → Matches: Berlin OR London (same result, explicit syntax)
// Other operators are NOT affected by array syntax
filter(users, { age: { $gte: 25, $lte: 35 } });
// → Uses operator logic, NOT array syntaxWhen to Use Array Syntax vs $in
Use Array Syntax when:
- You want clean, readable code
- You're filtering by multiple exact values
- You want OR logic on a single property
// ✅ Clean and intuitive
filter(users, { status: ['active', 'pending'] });Use Explicit $in when:
- You want to be explicit about using the $in operator
- You're combining with other operators
- You're migrating from MongoDB-style queries
// ✅ Explicit and clear intent
filter(users, { status: { $in: ['active', 'pending'] } });Both syntaxes produce identical results - choose based on your preference and code style.
Real-World Examples
// E-commerce: Filter products by multiple categories
filter(products, {
category: ['Electronics', 'Accessories'],
price: { $lte: 500 },
inStock: true
});
// User management: Find users with specific roles
filter(users, {
role: ['admin', 'moderator'],
active: true
});
// Analytics: Orders from multiple statuses
filter(orders, {
status: ['completed', 'shipped', 'delivered'],
amount: { $gte: 100 }
});
// Content filtering: Posts with multiple tags
filter(posts, {
tags: ['javascript', 'typescript', 'react'],
published: true
});String Operators
All string operators respect the caseSensitive configuration option (defaults to false).
$startsWith - Starts With
Returns items where the string property starts with the specified value.
const users = [
{ name: 'Alice' },
{ name: 'Bob' },
{ name: 'Alex' }
];
filter(users, {
name: { $startsWith: 'Al' }
});
// → Returns: Alice and Alex$endsWith - Ends With
Returns items where the string property ends with the specified value.
filter(users, {
name: { $endsWith: 'ce' }
});
// → Returns: Alice$contains - String Contains
Returns items where the string property contains the specified substring.
filter(users, {
name: { $contains: 'li' }
});
// → Returns: Alice$regex - Regular Expression Match
Matches strings against a regular expression pattern. Accepts either a string pattern or a RegExp object.
// String pattern
filter(users, { email: { $regex: '^[a-z]+@example\\.com$' } });
// → Returns users with emails matching the pattern
// RegExp object
filter(users, { phone: { $regex: /^\+1-\d{3}-\d{4}$/ } });
// → Returns users with US phone numbers
// Complex patterns
filter(products, { sku: { $regex: '^[A-Z]{3}-\\d{4}-[A-Z]$' } });
// → Returns products with SKU format like "ABC-1234-X"
// Email validation
filter(users, { email: { $regex: '^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$' } });
// → Returns users with valid email format
// Phone number patterns
filter(users, { phone: { $regex: '^\\+1-\\d{3}-\\d{4}$' } });
// → Returns US phone numbers in format +1-555-0123Case Sensitivity:
- String patterns respect the
caseSensitiveconfig (default: case-insensitive) - RegExp objects use their own flags (e.g.,
/pattern/ifor case-insensitive)
// Case-insensitive by default
filter(users, { name: { $regex: '^alice$' } });
// → Returns: Alice (case-insensitive)
// Case-sensitive with config
filter(users, { name: { $regex: '^alice$' } }, { caseSensitive: true });
// → Returns: [] (no match)
// Case-insensitive with RegExp flag
filter(users, { name: { $regex: /^alice$/i } });
// → Returns: Alice (case-insensitive regardless of config)Common Use Cases:
- Email validation:
^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ - Phone numbers:
^\+\d{1,3}-\d{3}-\d{4}$ - Zip codes:
^\d{5}(-\d{4})?$ - Usernames:
^[a-zA-Z0-9_]{3,16}$ - URLs:
^https?://[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}(/.*)?$
$match - Pattern Match (Alias)
$match is an alias for $regex and works identically.
filter(users, { username: { $match: '^[a-z]+\\d+$' } });
// Same as: { username: { $regex: '^[a-z]+\\d+$' } }
// Using RegExp object
filter(products, { code: { $match: /^[A-Z]{2}\d{4}$/ } });
// → Returns products with codes like "AB1234"Case Sensitivity
By default, string operators are case-insensitive:
filter(users, { name: { $startsWith: 'al' } });
// → Returns: Alice and Alex (case-insensitive)
filter(users, { name: { $startsWith: 'al' } }, { caseSensitive: true });
// → Returns: [] (case-sensitive, no match)Advanced Regex Patterns
Email Validation
const users = [
{ email: 'valid@example.com' },
{ email: 'invalid@' },
{ email: 'another.valid+tag@domain.co.uk' }
];
// RFC 5322 simplified email pattern
filter(users, {
email: { $regex: '^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$' }
});
// → Returns: valid@example.com, another.valid+tag@domain.co.ukPhone Number Patterns
const contacts = [
{ phone: '+1-555-0123' },
{ phone: '555-0123' },
{ phone: '+44-20-7123-4567' },
{ phone: 'invalid' }
];
// US phone numbers
filter(contacts, {
phone: { $regex: '^\\+1-\\d{3}-\\d{4}$' }
});
// → Returns: +1-555-0123
// International format
filter(contacts, {
phone: { $regex: '^\\+\\d{1,3}-\\d{2,4}-\\d{4,10}$' }
});
// → Returns: +1-555-0123, +44-20-7123-4567URL Validation
const links = [
{ url: 'https://example.com' },
{ url: 'http://sub.domain.com/path' },
{ url: 'ftp://files.com' },
{ url: 'not-a-url' }
];
// HTTP/HTTPS URLs only
filter(links, {
url: { $regex: '^https?://[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}(/.*)?$' }
});
// → Returns: https://example.com, http://sub.domain.com/pathUsername Validation
const users = [
{ username: 'john_doe123' },
{ username: 'alice' },
{ username: 'bob@invalid' },
{ username: 'x' }
];
// Alphanumeric + underscore, 3-16 characters
filter(users, {
username: { $regex: '^[a-zA-Z0-9_]{3,16}$' }
});
// → Returns: john_doe123, alicePostal Code Patterns
const addresses = [
{ zip: '12345' },
{ zip: '12345-6789' },
{ zip: 'SW1A 1AA' },
{ zip: 'invalid' }
];
// US ZIP codes (5 digits or ZIP+4)
filter(addresses, {
zip: { $regex: '^\\d{5}(-\\d{4})?$' }
});
// → Returns: 12345, 12345-6789
// UK postcodes
filter(addresses, {
zip: { $regex: '^[A-Z]{1,2}\\d{1,2}[A-Z]?\\s?\\d[A-Z]{2}$' }
});
// → Returns: SW1A 1AACase-Insensitive Regex
// Using string pattern (respects caseSensitive config)
filter(users, {
name: { $regex: '^john' }
}, { caseSensitive: false });
// → Matches: John, JOHN, john
// Using RegExp with flags (ignores config)
filter(users, {
name: { $regex: /^john/i }
});
// → Always case-insensitiveComplex Patterns
// Product SKU format: ABC-1234-X
filter(products, {
sku: { $regex: '^[A-Z]{3}-\\d{4}-[A-Z]$' }
});
// Date format: YYYY-MM-DD
filter(records, {
date: { $regex: '^\\d{4}-\\d{2}-\\d{2}$' }
});
// IPv4 address
filter(servers, {
ip: { $regex: '^\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}$' }
});
// Credit card (basic pattern)
filter(payments, {
card: { $regex: '^\\d{4}-\\d{4}-\\d{4}-\\d{4}$' }
});Performance Considerations
// ✅ Good: Compile regex once
const emailPattern = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
filter(users, { email: { $regex: emailPattern } });
// ⚠️ Less efficient: String pattern compiled on each filter
filter(users, { email: { $regex: '^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$' } });
// 💡 Best: Use simpler operators when possible
filter(users, { email: { $endsWith: '@company.com' } });Common Regex Patterns Reference
| Pattern | Regex | Example |
|---|---|---|
^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ | user@example.com | |
| US Phone | ^\+1-\d{3}-\d{4}$ | +1-555-0123 |
| URL | ^https?://[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}(/.*)?$ | https://example.com |
| ZIP Code | ^\d{5}(-\d{4})?$ | 12345 or 12345-6789 |
| Username | ^[a-zA-Z0-9_]{3,16}$ | john_doe123 |
| Hex Color | ^#[0-9A-Fa-f]{6}$ | #FF5733 |
| IPv4 | ^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$ | 192.168.1.1 |
| Date (YYYY-MM-DD) | ^\d{4}-\d{2}-\d{2}$ | 2025-10-25 |
Escaping Special Characters
Remember to escape special regex characters in string patterns:
// Special characters: . * + ? ^ $ { } ( ) | [ ] \
// ❌ Wrong: . matches any character
filter(files, { name: { $regex: 'file.txt' } });
// ✅ Correct: Escape the dot
filter(files, { name: { $regex: 'file\\.txt' } });
// ❌ Wrong: * is invalid regex
filter(files, { name: { $regex: '*.txt' } });
// ✅ Correct: Use .* for wildcard
filter(files, { name: { $regex: '.*\\.txt$' } });Logical Operators
Logical operators allow you to combine multiple conditions with AND, OR, and NOT logic. They support recursive nesting for complex queries.
$and - Logical AND
Returns items where all conditions in the array match.
import { filter } from '@mcabreradev/filter';
const products = [
{ name: 'Laptop', price: 1200, category: 'Electronics', inStock: true },
{ name: 'Mouse', price: 25, category: 'Accessories', inStock: true },
{ name: 'Desk', price: 350, category: 'Furniture', inStock: false }
];
// Simple AND - all conditions must match
filter(products, {
$and: [
{ category: 'Electronics' },
{ inStock: true }
]
});
// → Returns: Laptop
// AND with operators
filter(products, {
$and: [
{ price: { $gte: 100 } },
{ price: { $lte: 500 } },
{ inStock: true }
]
});
// → Returns: Desk would match price range but is out of stock, so returns []
// Nested AND conditions
filter(products, {
$and: [
{ category: { $in: ['Electronics', 'Accessories'] } },
{ price: { $lt: 1000 } },
{ inStock: { $eq: true } }
]
});
// → Returns: MouseUse Case: When you need ALL conditions to be true simultaneously.
$or - Logical OR
Returns items where at least one condition in the array matches.
// Simple OR - any condition can match
filter(products, {
$or: [
{ category: 'Electronics' },
{ category: 'Accessories' }
]
});
// → Returns: Laptop and Mouse
// OR with different properties
filter(products, {
$or: [
{ price: { $lt: 50 } },
{ category: 'Furniture' }
]
});
// → Returns: Mouse ($25) and Desk (Furniture)
// OR with complex conditions
filter(products, {
$or: [
{ $and: [{ category: 'Electronics' }, { price: { $gt: 1000 } }] },
{ $and: [{ category: 'Accessories' }, { inStock: true }] }
]
});
// → Returns: Laptop (Electronics > $1000) and Mouse (Accessories in stock)Use Case: When you want items matching ANY of several criteria.
$not - Logical NOT
Returns items where the condition does NOT match. Accepts a single expression (not an array).
// Simple NOT
filter(products, {
$not: { category: 'Furniture' }
});
// → Returns: Laptop and Mouse (everything except Furniture)
// NOT with operators
filter(products, {
$not: { price: { $gt: 500 } }
});
// → Returns: Mouse and Desk (price <= $500)
// NOT with complex conditions
filter(products, {
$not: {
$and: [
{ category: 'Furniture' },
{ inStock: false }
]
}
});
// → Returns: Laptop, Mouse, and any Furniture that IS in stockUse Case: When you want to exclude items matching certain criteria.
Nested Logical Operators
Logical operators can be nested to create complex queries:
// Complex nested query: (Electronics OR Accessories) AND in stock AND affordable
filter(products, {
$and: [
{
$or: [
{ category: 'Electronics' },
{ category: 'Accessories' }
]
},
{ inStock: true },
{ price: { $lt: 100 } }
]
});
// → Returns: Mouse (Accessories, in stock, $25)
// NOT with nested conditions
filter(products, {
$not: {
$or: [
{ price: { $gt: 1000 } },
{ inStock: false }
]
}
});
// → Returns: Mouse (not expensive and not out of stock)
// Deeply nested logic
filter(products, {
$or: [
{
$and: [
{ category: 'Electronics' },
{ $not: { price: { $lt: 500 } } }
]
},
{
$and: [
{ category: 'Accessories' },
{ inStock: true }
]
}
]
});
// → Returns: Laptop (Electronics >= $500) and Mouse (Accessories in stock)Combining Logical Operators with Field Conditions
You can mix logical operators with regular field-level conditions:
// Field condition + logical operator
filter(products, {
category: 'Electronics',
$and: [
{ price: { $gte: 100 } },
{ inStock: true }
]
});
// → Returns: Laptop (Electronics, price >= $100, in stock)
// Multiple logical operators
filter(products, {
inStock: true,
$or: [
{ category: 'Electronics' },
{ price: { $lt: 50 } }
],
$not: { name: { $startsWith: 'Old' } }
});
// → Returns: Items in stock that are either Electronics OR cheap, but NOT starting with "Old"Real-World Logical Operator Examples
interface User {
name: string;
age: number;
role: string;
active: boolean;
lastLogin: Date;
}
const users: User[] = [
{ name: 'Alice', age: 30, role: 'admin', active: true, lastLogin: new Date('2025-10-20') },
{ name: 'Bob', age: 25, role: 'user', active: false, lastLogin: new Date('2025-09-15') },
{ name: 'Charlie', age: 35, role: 'moderator', active: true, lastLogin: new Date('2025-10-24') }
];
// Find active admins or moderators
filter(users, {
$and: [
{ active: true },
{ $or: [{ role: 'admin' }, { role: 'moderator' }] }
]
});
// → Returns: Alice and Charlie
// Find users who need attention (inactive OR haven't logged in recently)
filter(users, {
$or: [
{ active: false },
{ lastLogin: { $lt: new Date('2025-10-01') } }
]
});
// → Returns: Bob (inactive and old login)
// Find eligible users (NOT guest AND (active OR recent login))
filter(users, {
$and: [
{ $not: { role: 'guest' } },
{
$or: [
{ active: true },
{ lastLogin: { $gte: new Date('2025-10-15') } }
]
}
]
});
// → Returns: Alice and CharlieAvailable: $and, $or, $not
Combining Operators
Multiple Operators on Same Property
You can use multiple operators on the same property:
filter(products, {
price: {
$gte: 100,
$lte: 500,
$ne: 300
}
});
// → Returns products priced between $100-$500, excluding $300Multiple Properties with Operators
You can use operators on different properties:
filter(products, {
price: { $gte: 100 },
category: { $in: ['Electronics', 'Furniture'] },
name: { $startsWith: 'M' }
});
// → Returns products matching all conditionsMixing Operators with Legacy Syntax
Operators work seamlessly with the existing filter syntax:
filter(products, {
category: 'Electronics', // Simple equality
name: 'M%', // Wildcard pattern
price: { $gte: 100, $lte: 500 } // Operators
});Real-World Examples
E-commerce Product Filtering
interface Product {
id: number;
name: string;
price: number;
category: string;
tags: string[];
inStock: boolean;
rating: number;
}
const products: Product[] = [
{
id: 1,
name: 'Laptop Pro',
price: 1200,
category: 'Electronics',
tags: ['computer', 'portable', 'gaming'],
inStock: true,
rating: 4.5
},
// ... more products
];
// Find affordable electronics in stock
filter(products, {
category: { $in: ['Electronics', 'Accessories'] },
price: { $lte: 500 },
inStock: { $eq: true }
});
// Find highly-rated gaming products
filter(products, {
tags: { $contains: 'gaming' },
rating: { $gte: 4.0 }
});
// Find products with specific name patterns
filter(products, {
name: { $startsWith: 'Laptop' },
price: { $lt: 1500 }
});User Management
interface User {
id: number;
username: string;
email: string;
age: number;
roles: string[];
createdAt: Date;
}
const users: User[] = [
// ... user data
];
// Find adult users created this year
filter(users, {
age: { $gte: 18 },
createdAt: {
$gte: new Date('2025-01-01'),
$lte: new Date('2025-12-31')
}
});
// Find users with specific roles
filter(users, {
roles: { $contains: 'admin' }
});
// Find users with email from specific domains
filter(users, {
email: { $endsWith: '@company.com' }
});Analytics and Reporting
interface Order {
id: number;
customerId: number;
amount: number;
status: string;
items: string[];
orderDate: Date;
}
const orders: Order[] = [
// ... order data
];
// High-value orders from last quarter
filter(orders, {
amount: { $gte: 1000 },
orderDate: {
$gte: new Date('2025-01-01'),
$lte: new Date('2025-03-31')
},
status: { $in: ['completed', 'shipped'] }
});
// Orders with specific products
filter(orders, {
items: { $contains: 'PRODUCT-123' },
amount: { $lt: 500 }
});Type Safety
All operators are fully typed with TypeScript:
import type { ComparisonOperators, ArrayOperators, StringOperators } from '@mcabreradev/filter';
// Type-safe operator usage
const priceFilter: ComparisonOperators = {
$gte: 100,
$lte: 500
};
const categoryFilter: ArrayOperators = {
$in: ['Electronics', 'Furniture']
};
const nameFilter: StringOperators = {
$startsWith: 'Lap'
};Performance Notes
- Operators are optimized with early exit strategies
- Multiple operators on the same property are evaluated efficiently
- String operators respect the global
caseSensitiveconfiguration - Operator detection is cached for repeated queries (when
enableCache: true)
Migration from v3.x
Operators are a new feature in v5.0.0 and are 100% backward compatible. All existing v3.x syntax continues to work:
// v3.x syntax still works
filter(users, 'Berlin');
filter(users, { city: 'Berlin' });
filter(users, (u) => u.age > 25);
// v5.0.0 new operator syntax
filter(users, { age: { $gt: 25 } });