Query DSL

The FLXBL Query DSL is a JSON-based query language that supports MongoDB-style operators and graph traversal. Query complex data without writing SQL or Cypher.

Basic Query Structure

// POST /api/v1/dynamic/Product/query
{
  "where": {
    "price": { "$lte": 100 },
    "inStock": { "$eq": true }
  },
  "orderBy": "price",
  "orderDirection": "ASC",
  "limit": 20
}

Query options:

Option Type Description
where object Filter conditions
traverse array Graph relationship traversal
orderBy string Field to sort by
orderDirection "ASC" | "DESC" Sort direction
limit number Maximum results to return
offset number Number of results to skip

Comparison Operators

// Comparison operators
{
  "where": {
    "price": { "$eq": 99.99 },      // Equal
    "price": { "$neq": 99.99 },     // Not equal
    "price": { "$gt": 50 },         // Greater than
    "price": { "$gte": 50 },        // Greater than or equal
    "price": { "$lt": 100 },        // Less than
    "price": { "$lte": 100 },       // Less than or equal
    "status": { "$in": ["active", "pending"] }      // In array
  }
}
Operator Description Example
$eq Equal to { "status": { "$eq": "active" } }
$neq Not equal to { "status": { "$neq": "deleted" } }
$gt Greater than { "price": { "$gt": 50 } }
$gte Greater than or equal { "price": { "$gte": 50 } }
$lt Less than { "price": { "$lt": 100 } }
$lte Less than or equal { "price": { "$lte": 100 } }
$in Value in array { "status": { "$in": ["a", "b"] } }

Array Operators

For array fields, use $contains to check if the array includes a specific value:

// Array operators (for array fields)
{
  "where": {
    "tags": { "$contains": "featured" }   // Check if array contains value
  }
}
Operator Description Example
$contains Array contains value { "tags": { "$contains": "featured" } }

String Operators

For string fields, FLXBL provides case-insensitive matching operators:

// String operators (case-insensitive)
{
  "where": {
    "name": { "$contains": "widget" },       // Substring match
    "email": { "$startsWith": "admin" },     // Prefix match
    "email": { "$endsWith": "@example.com" } // Suffix match
  }
}
Operator Description Example
$contains Substring match (case-insensitive) { "name": { "$contains": "widget" } }
$startsWith Prefix match (case-insensitive) { "email": { "$startsWith": "admin" } }
$endsWith Suffix match (case-insensitive) { "email": { "$endsWith": "@example.com" } }

Note: The $contains operator works differently based on field type: for array fields, it checks if the array includes the value; for string fields, it performs a case-insensitive substring search.

Logical Operators

Combine multiple conditions with $and and $or:

// Logical operators
{
  "where": {
    "$and": [
      { "price": { "$gte": 10 } },
      { "price": { "$lte": 100 } }
    ]
  }
}

// OR condition
{
  "where": {
    "$or": [
      { "status": { "$eq": "featured" } },
      { "price": { "$lt": 20 } }
    ]
  }
}

// Combining AND and OR
{
  "where": {
    "$and": [
      { "inStock": { "$eq": true } },
      {
        "$or": [
          { "category": { "$eq": "electronics" } },
          { "category": { "$eq": "accessories" } }
        ]
      }
    ]
  }
}

Graph Traversal

The traverse option lets you follow relationships in the graph. This is one of FLXBL's most powerful features.

// Graph traversal - follow relationships
{
  "where": {
    "name": { "$eq": "Wireless Headphones" }
  },
  "traverse": [{
    "relationship": "BELONGS_TO",
    "direction": "out",
    "where": {
      "name": { "$eq": "Electronics" }
    }
  }]
}

// Multi-hop traversal
{
  "where": {
    "email": { "$eq": "alice@example.com" }
  },
  "traverse": [
    {
      "relationship": "PURCHASED",
      "direction": "out"
    },
    {
      "relationship": "BELONGS_TO",
      "direction": "out",
      "where": {
        "name": { "$eq": "Electronics" }
      }
    }
  ]
}

Traverse options:

Option Type Description
relationship string Name of the relationship to follow
direction "in" | "out" Direction to traverse
where object Filter on the related entity

Pagination

// Pagination and sorting
{
  "where": {
    "status": { "$eq": "active" }
  },
  "orderBy": "createdAt",
  "orderDirection": "DESC",
  "limit": 10,
  "offset": 20
}

Complete Example

Here's a complete example that combines multiple operators with graph traversal:

// Complete query example
curl -X POST https://api.flxbl.dev/api/v1/dynamic/Product/query \
  -H "Authorization: Bearer flxbl_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "where": {
      "$and": [
        { "price": { "$gte": 10, "$lte": 500 } },
        { "inStock": { "$eq": true } },
        {
          "$or": [
            { "tags": { "$contains": "featured" } },
            { "tags": { "$contains": "sale" } }
          ]
        }
      ]
    },
    "traverse": [{
      "relationship": "BELONGS_TO",
      "direction": "out",
      "where": {
        "slug": { "$in": ["electronics", "accessories"] }
      }
    }],
    "orderBy": "price",
    "orderDirection": "ASC",
    "limit": 20
  }'

TypeScript Client

Use the generated TypeScript client for type-safe queries:

// TypeScript client usage
import { createFlxblClient } from './schemas';

const client = createFlxblClient({
  baseUrl: 'https://api.flxbl.dev',
  apiKey: 'flxbl_your_api_key'
});

// Query with type safety
const products = await client.query('Product', {
  where: {
    price: { $gte: 10, $lte: 100 },
    inStock: { $eq: true }
  },
  traverse: [{
    relationship: 'BELONGS_TO',
    direction: 'out',
    where: { slug: { $eq: 'electronics' } }
  }],
  orderBy: 'price',
  orderDirection: 'ASC',
  limit: 20
});

console.log(products); // Typed as Product[]

Best Practices

  • Limit results: Always set a reasonable limit to avoid returning too much data
  • Optimize traversals: Start with the most selective condition first
  • Cache when possible: Use Redis caching for frequently repeated queries
  • Test with real data: Query performance varies with data size

Next Steps