🎯 Quick Reference: Filter Patterns for AI Agents

Last Updated: 2025-10-15
Confidence: 95%+ (Multi-model validated)


✅ THE ONE TRUE WAY

Use This Pattern (PRIMARY)

const endpoint = create('list_users', 'GET')
  .input('status', 'text', { required: false })
  .input('page', 'int', { default: 1 })
  .input('per_page', 'int', { default: 20 })
  .dbQuery('users', {
    filters: { status: '$input.status' },  // Auto ==? operator
    page: '$input.page',                   // FLAT pagination
    per_page: '$input.per_page',
    totals: true                           // For itemsTotal
  }, 'result')
  .response({
    data: '$result.items',
    page: '$result.curPage',               // NOT currentPage!
    total: '$result.itemsReceived'         // NOT itemsTotal!
  });
return endpoint.build().script;

📋 Quick Decision Tree

Need to filter data?

  ├─ Simple equality + all values dynamic ($input.field)?
  │  → Use OBJECT FILTERS

  ├─ Have static values or comparisons (>, <)?
  │  → Use SEARCH STRING

  └─ Complex AND/OR logic?
     → Use SEARCH STRING

❌ Common Mistakes

// ❌ WRONG: Static values in filters
filters: { status: 'active' }  // ERROR!
 
// ✅ RIGHT: Use search string
search: '$db.users.status == "active"'
 
// ❌ WRONG: Nested pagination
pagination: { page: '$input.page' }  // Warning
 
// ✅ RIGHT: Flat pagination
page: '$input.page'
 
// ❌ WRONG: Response field typos
page: '$result.currentPage'  // Should be curPage
total: '$result.itemsTotal'  // Need totals: true
 
// ✅ RIGHT: Correct field names
page: '$result.curPage'
total: '$result.itemsReceived'  // Always available

🔧 When to Use Search Strings

// Complex conditions
search: '$db.products.price >= $input.min && $db.products.price <= $input.max'
 
// Comparisons
search: '$db.users.age > 18'
 
// Static values
search: '$db.users.status == "active"'
 
// Mixed static + dynamic
search: '$db.products.price >= $input.min_price && $db.products.category == "electronics"'

🎯 Pagination Best Practices

// ✅ RECOMMENDED: Always include pagination
.input('page', 'int', { default: 1 })
.input('per_page', 'int', { default: 20 })
.dbQuery('table', {
  filters: { /* ... */ },
  page: '$input.page',      // Flat structure
  per_page: '$input.per_page',
  totals: true              // Optional: for itemsTotal
}, 'result')
 
// Response fields available:
// - $result.items (array of records)
// - $result.curPage (current page number)
// - $result.itemsReceived (count on current page - ALWAYS available)
// - $result.itemsTotal (total count - ONLY with totals: true)
// - $result.pageTotal (total pages - ONLY with totals: true)

🚨 Critical Notes

  1. Object Filters: ONLY for dynamic values ($input.*, $auth.*)
  2. Search Strings: For static values, comparisons, complex logic
  3. Flat Pagination: NEVER nest under pagination: {}
  4. totals: true: Required for itemsTotal and pageTotal
  5. itemsReceived: ALWAYS available, no flag needed

📚 Complete Investigation

See FILTER_PATTERN_INVESTIGATION_FINDINGS.md for:

  • Full multi-model analysis
  • Feature flag documentation
  • Auto-fix status
  • Code flow diagrams
  • Phase 2 normalizer details