Back to Blog

OQL Query Guide: 20 Real Examples

OQL (Ontology Query Language) is the declarative query language of the coomia-dip platform, purpose-built for the Ontology data model. It is more business-semantic than SQL, supporting joint queries across objects, relations, and properties, as well as graph traversal, aggregation, and reasoning integration. This article covers OQL's full query capabilities through 20 real-world examples, from basics to advanced patterns.

Coomia DIPPublished on January 15, 202612 min read
Share this articleTwitter / X
“

Series: S12 Developer Tutorials · Article 6 | Level: Intermediate | Reading Time: 15 min

OQL Query Guide: 20 Real Examples

#TL;DR

OQL (Ontology Query Language) is the declarative query language of the coomia-dip platform, purpose-built for the Ontology data model. It is more business-semantic than SQL, supporting joint queries across objects, relations, and properties, as well as graph traversal, aggregation, and reasoning integration. This article covers OQL's full query capabilities through 20 real-world examples, from basics to advanced patterns.

#1. OQL Overview

#1.1 What is OQL?

OQL is the native query language of the coomia-dip platform, running on the Control Layer (Control Layer). Unlike traditional SQL, OQL uses Ontology as its core abstraction: you query "objects" and "relations," not "tables" and "rows."

Code
SQL:   SELECT * FROM projects WHERE status = 'active'
OQL:   FIND Project WHERE status = 'active'

#1.2 Key Differences Between OQL and SQL

FeatureSQLOQL
Query TargetTables / RowsObjects / Relations
Join MethodJOINTRAVERSE
Data ModelRelationalOntology
Graph TraversalMulti-level JOINNative TRAVERSE
Permission FilteringManual WHEREAutomatic ABAC Integration
Type SafetyWeakSchema-enforced

#1.3 OQL Execution Architecture

Code
Client (SDK / API)
    │
    ▼
Control Layer (gRPC)
    │  ① Parse OQL → AST
    │  ② Schema Validation
    │  ③ Permission Filter Injection
    │  ④ Query Optimization
    ▼
Data Layer (Doris / Iceberg)
    │  ⑤ Execute Query
    ▼
Result Set → Object Mapping

#2. Environment Setup

#2.1 Install the SDK

Bash
pip install ontology-sdk>=1.0.0

#2.2 Initialize Connection

Python
from ontology_sdk import OntoPlatform

platform = OntoPlatform(
    control_plane_url="localhost:50051",
    data_plane_url="localhost:50052",
    auth_token="your-token"
)

# Get OQL client
oql = platform.oql

#2.3 Sample Data Model

All examples in this article are based on the following Ontology model:

YAML
object_types:
  - Employee:
      properties: [name, email, department, salary, hire_date, level]
  - Project:
      properties: [name, status, priority, budget, start_date, end_date]
  - Department:
      properties: [name, code, location, head_count]
  - Task:
      properties: [title, status, assignee_rid, due_date, story_points]
  - Customer:
      properties: [name, industry, region, annual_revenue, tier]

relations:
  - works_in: Employee -> Department
  - participates_in: Employee -> Project
  - owns_project: Department -> Project
  - has_task: Project -> Task
  - assigned_to: Task -> Employee
  - serves: Project -> Customer

#3. Basic Queries (Examples 1-5)

#Example 1: Simple Object Query

Find all in-progress projects:

Python
results = oql.execute("""
    FIND Project
    WHERE status = 'in_progress'
    SELECT name, priority, budget
    ORDER BY priority DESC
""")

for project in results:
    print(f"{project.name} | Priority: {project.priority} | Budget: {project.budget}")

Output:

Code
Smart Factory Monitoring | Priority: critical | Budget: 5000000
Supply Chain Optimization | Priority: high | Budget: 3200000
Customer 360 Profile | Priority: medium | Budget: 1800000

#Example 2: Multi-Condition Filtering

Find high-salary senior employees:

Python
results = oql.execute("""
    FIND Employee
    WHERE salary > 30000
      AND level IN ('senior', 'staff', 'principal')
      AND department != 'HR'
    SELECT name, level, salary, department
    ORDER BY salary DESC
    LIMIT 20
""")

Supported OQL Operators:

  • Comparison: =, !=, >, <, >=, <=
  • Set: IN, NOT IN
  • Pattern: LIKE, CONTAINS, STARTS_WITH
  • Null: IS NULL, IS NOT NULL
  • Logical: AND, OR, NOT

#Example 3: Property Projection and Aliases

Python
results = oql.execute("""
    FIND Project
    WHERE status = 'in_progress'
    SELECT
        name AS project_name,
        budget AS total_budget,
        (end_date - start_date) AS duration_days,
        priority
""")

#Example 4: Paginated Queries

Python
# Page 1
page1 = oql.execute("""
    FIND Employee
    WHERE department = 'Engineering'
    SELECT name, email, level
    ORDER BY hire_date ASC
    LIMIT 20 OFFSET 0
""")

# Page 2
page2 = oql.execute("""
    FIND Employee
    WHERE department = 'Engineering'
    SELECT name, email, level
    ORDER BY hire_date ASC
    LIMIT 20 OFFSET 20
""")

# SDK-wrapped pagination
paginator = oql.paginate(
    query="FIND Employee WHERE department = 'Engineering'",
    page_size=20
)

for page in paginator:
    for emp in page.results:
        print(emp.name)
    print(f"--- Page {page.page_number} of {page.total_pages} ---")

#Example 5: Fuzzy Search and Full-Text Retrieval

Python
# Property pattern matching
results = oql.execute("""
    FIND Project
    WHERE name LIKE '%supply chain%'
       OR description CONTAINS 'optimization'
    SELECT name, description
""")

# Full-text search mode
results = oql.execute("""
    FIND Project
    SEARCH 'supply chain risk warning'
    SELECT name, description, _score
    ORDER BY _score DESC
    LIMIT 10
""")

#4. Relation Traversal Queries (Examples 6-10)

#Example 6: Single-Level Relation Traversal

Find all employees in a specific department:

Python
results = oql.execute("""
    FIND Employee
    TRAVERSE works_in -> Department
    WHERE Department.name = 'Engineering'
    SELECT Employee.name, Employee.level, Employee.salary
""")

Equivalent gRPC call via SDK:

Python
dept = platform.objects.get("Department", filters={"name": "Engineering"})
employees = platform.relations.get_related(
    source_rid=dept.rid,
    relation_type="works_in",
    direction="inbound"
)

#Example 7: Multi-Level Relation Traversal

Find all employees involved in projects for a specific customer:

Python
results = oql.execute("""
    FIND Employee
    TRAVERSE participates_in -> Project
    TRAVERSE serves -> Customer
    WHERE Customer.name = 'Huawei Technologies'
    SELECT
        Employee.name AS employee_name,
        Project.name AS project_name,
        Customer.name AS customer_name
""")

#Example 8: Reverse Relation Traversal

Find all tasks assigned to an employee and their parent projects:

Python
results = oql.execute("""
    FIND Task
    TRAVERSE assigned_to -> Employee
    WHERE Employee.name = 'John Smith'
    INCLUDE
        TRAVERSE has_task <- Project
        SELECT Project.name AS project_name
    SELECT Task.title, Task.status, Task.due_date, project_name
    ORDER BY Task.due_date ASC
""")

#Example 9: Relation Property Filtering

Python
results = oql.execute("""
    FIND Employee
    TRAVERSE participates_in -> Project
    WHERE participates_in.role = 'tech_lead'
      AND Project.status = 'in_progress'
    SELECT
        Employee.name,
        participates_in.role,
        participates_in.joined_date,
        Project.name AS project_name
""")

#Example 10: Graph Path Query

Find connection paths between two objects:

Python
results = oql.execute("""
    PATH FROM Employee WHERE name = 'John Smith'
    TO Customer WHERE name = 'Huawei Technologies'
    MAX_DEPTH 4
    VIA [participates_in, serves, owns_project, works_in]
""")

for path in results:
    print(" -> ".join([node.type_name + ":" + node.name for node in path.nodes]))

Output:

Code
Employee:John Smith -> Project:Smart Factory Monitoring -> Customer:Huawei Technologies
Employee:John Smith -> Department:Engineering -> Project:Supply Chain Optimization -> Customer:Huawei Technologies

#5. Aggregation and Analytics Queries (Examples 11-15)

#Example 11: Basic Aggregation

Python
results = oql.execute("""
    FIND Employee
    GROUP BY department
    AGGREGATE
        COUNT(*) AS total_count,
        AVG(salary) AS avg_salary,
        MAX(salary) AS max_salary,
        MIN(salary) AS min_salary
    ORDER BY avg_salary DESC
""")

for row in results:
    print(f"{row.department}: {row.total_count} employees, "
          f"avg salary: {row.avg_salary:.0f}")

#Example 12: Multi-Dimensional Aggregation

Python
results = oql.execute("""
    FIND Task
    TRAVERSE has_task <- Project
    GROUP BY Project.name, Task.status
    AGGREGATE
        COUNT(*) AS task_count,
        SUM(Task.story_points) AS total_points
    ORDER BY Project.name, Task.status
""")

#Example 13: Time-Series Aggregation

Python
results = oql.execute("""
    FIND Employee
    GROUP BY DATE_TRUNC('month', hire_date) AS hire_month
    AGGREGATE
        COUNT(*) AS new_hires
    WHERE hire_date >= '2025-01-01'
    ORDER BY hire_month ASC
""")

for row in results:
    bar = '#' * row.new_hires
    print(f"{row.hire_month}: {bar} ({row.new_hires})")

#Example 14: HAVING Clause Filtering

Python
results = oql.execute("""
    FIND Project
    TRAVERSE has_task -> Task
    GROUP BY Project.name
    AGGREGATE
        COUNT(*) AS total_tasks,
        COUNT(CASE WHEN Task.status = 'done' THEN 1 END) AS done_tasks,
        ROUND(
            COUNT(CASE WHEN Task.status = 'done' THEN 1 END) * 100.0
            / COUNT(*), 1
        ) AS completion_rate
    HAVING total_tasks > 5 AND completion_rate < 50
    ORDER BY completion_rate ASC
""")

print("=== Projects Behind Schedule ===")
for row in results:
    print(f"{row.project_name}: {row.completion_rate}% "
          f"({row.done_tasks}/{row.total_tasks})")

#Example 15: Cross-Object Statistics

Python
results = oql.execute("""
    FIND Department
    INCLUDE
        TRAVERSE works_in <- Employee
        AGGREGATE COUNT(*) AS emp_count, AVG(Employee.salary) AS avg_salary
    INCLUDE
        TRAVERSE owns_project <- Project
        WHERE Project.status = 'in_progress'
        AGGREGATE COUNT(*) AS active_projects, SUM(Project.budget) AS total_budget
    SELECT
        Department.name,
        Department.location,
        emp_count,
        avg_salary,
        active_projects,
        total_budget
    ORDER BY total_budget DESC
""")

#6. Advanced Queries (Examples 16-20)

#Example 16: Subqueries

Python
results = oql.execute("""
    FIND Employee
    WHERE salary > (
        FIND Employee
        WHERE department = $self.department
        AGGREGATE AVG(salary)
    )
    SELECT name, department, salary
    ORDER BY department, salary DESC
""")

#Example 17: WITH Precomputation (CTE Equivalent)

Python
results = oql.execute("""
    WITH dept_stats AS (
        FIND Employee
        GROUP BY department
        AGGREGATE
            AVG(salary) AS avg_salary,
            COUNT(*) AS emp_count
    )
    FIND Employee
    JOIN dept_stats ON Employee.department = dept_stats.department
    WHERE Employee.salary > dept_stats.avg_salary * 1.5
    SELECT
        Employee.name,
        Employee.department,
        Employee.salary,
        dept_stats.avg_salary AS dept_avg,
        ROUND(Employee.salary / dept_stats.avg_salary * 100, 1) AS ratio_pct
    ORDER BY ratio_pct DESC
""")

#Example 18: Conditional Expressions

Python
results = oql.execute("""
    FIND Project
    SELECT
        name,
        budget,
        CASE
            WHEN budget > 5000000 THEN 'Large'
            WHEN budget > 2000000 THEN 'Medium'
            WHEN budget > 500000 THEN 'Small'
            ELSE 'Micro'
        END AS project_scale,
        CASE
            WHEN end_date < NOW() AND status != 'done' THEN 'Overdue'
            WHEN end_date < NOW() + INTERVAL '7 days' THEN 'Due Soon'
            ELSE 'On Track'
        END AS deadline_status
    ORDER BY budget DESC
""")

#Example 19: Parameterized Queries and Injection Prevention

Python
# Parameterized query — prevents OQL injection
results = oql.execute(
    """
    FIND Employee
    WHERE department = :dept
      AND level IN :levels
      AND hire_date >= :start_date
    SELECT name, level, salary
    ORDER BY salary DESC
    LIMIT :page_size OFFSET :offset
    """,
    params={
        "dept": "Engineering",
        "levels": ["senior", "staff", "principal"],
        "start_date": "2024-01-01",
        "page_size": 20,
        "offset": 0
    }
)

# Batch parameterized execution
batch_results = oql.execute_batch(
    "FIND Employee WHERE department = :dept AGGREGATE COUNT(*) AS cnt",
    params_list=[
        {"dept": "Engineering"},
        {"dept": "Product"},
        {"dept": "Design"},
    ]
)

for dept_result in batch_results:
    print(f"{dept_result.params['dept']}: {dept_result.results[0].cnt} employees")

#Example 20: Reasoning-Integrated Queries

OQL can integrate with the Intelligence Layer reasoning engine:

Python
# Rule-based reasoning query
results = oql.execute("""
    FIND Employee
    WHERE INFERRED risk_level = 'high'
    SELECT
        name, department,
        INFERRED risk_level,
        INFERRED risk_factors,
        INFERRED recommended_actions
""")

# The INFERRED keyword triggers the reasoning engine
# Intelligence Layer computes derived properties based on rules and knowledge graph

# Knowledge graph reasoning query
results = oql.execute("""
    FIND Customer
    WHERE INFERRED churn_probability > 0.7
    TRAVERSE serves <- Project
    SELECT
        Customer.name,
        Customer.tier,
        INFERRED Customer.churn_probability,
        INFERRED Customer.churn_reason,
        Project.name AS related_project
    ORDER BY INFERRED Customer.churn_probability DESC
""")

for row in results:
    print(f"WARNING: {row.customer_name} (Churn probability: {row.churn_probability:.1%})")
    print(f"  Reason: {row.churn_reason}")
    print(f"  Related project: {row.related_project}")

#7. OQL Best Practices

#7.1 Performance Optimization

Python
# Bad: full scan then filter
oql.execute("FIND Employee SELECT * WHERE salary > 50000")

# Good: select only needed fields, filter first
oql.execute("""
    FIND Employee
    WHERE salary > 50000
    SELECT name, salary, level
    LIMIT 100
""")

# Bad: N+1 query
for project in projects:
    tasks = oql.execute(f"FIND Task TRAVERSE has_task <- Project WHERE Project.rid = '{project.rid}'")

# Good: batch traversal
results = oql.execute("""
    FIND Project
    WHERE status = 'in_progress'
    INCLUDE
        TRAVERSE has_task -> Task
        SELECT Task.title, Task.status
    SELECT Project.name, tasks
""")

#7.2 Query Plan Analysis

Python
# Use EXPLAIN to view the query plan
plan = oql.explain("""
    FIND Employee
    TRAVERSE works_in -> Department
    WHERE Department.location = 'Shanghai'
    SELECT Employee.name, Employee.salary
""")

print(plan.to_tree())
# +-- ObjectScan: Employee (estimated: 5000 rows)
# +-- RelationLookup: works_in (index: btree)
# +-- Filter: Department.location = 'Shanghai' (selectivity: 0.15)
# +-- Project: [Employee.name, Employee.salary]
# Estimated cost: 750 | Uses indexes: [works_in_idx, dept_location_idx]

#7.3 Common Errors and Troubleshooting

ErrorCauseSolution
ObjectTypeNotFoundTypo in object type nameCheck Schema Registry
PropertyNotFoundProperty does not existUse platform.schema.describe("Employee")
PermissionDeniedABAC policy blocks accessCheck current user's permission policies
TraversalDepthExceededGraph traversal too deepAdjust MAX_DEPTH or restructure query
QueryTimeoutQuery execution timed outAdd indexes or restructure query

#8. Complete Example: Project Health Dashboard

Python
from ontology_sdk import OntoPlatform

platform = OntoPlatform(
    control_plane_url="localhost:50051",
    data_plane_url="localhost:50052"
)
oql = platform.oql

# Project overview
overview = oql.execute("""
    FIND Project
    GROUP BY status
    AGGREGATE COUNT(*) AS count, SUM(budget) AS total_budget
""")

print("=== Project Status Distribution ===")
for row in overview:
    print(f"  {row.status}: {row.count} projects, total budget: ${row.total_budget:,.0f}")

# Resource utilization
utilization = oql.execute("""
    FIND Employee
    INCLUDE
        TRAVERSE participates_in -> Project
        WHERE Project.status = 'in_progress'
        AGGREGATE COUNT(*) AS active_projects
    SELECT
        name, department, level, active_projects,
        CASE
            WHEN active_projects > 3 THEN 'Overloaded'
            WHEN active_projects = 0 THEN 'Idle'
            ELSE 'Normal'
        END AS workload_status
    ORDER BY active_projects DESC
""")

print("\n=== Resource Load ===")
overloaded = [r for r in utilization if r.workload_status == 'Overloaded']
idle = [r for r in utilization if r.workload_status == 'Idle']
print(f"  Overloaded: {len(overloaded)} employees")
print(f"  Idle: {len(idle)} employees")

# At-risk projects
at_risk = oql.execute("""
    FIND Project
    WHERE status = 'in_progress'
      AND end_date < NOW() + INTERVAL '14 days'
    INCLUDE
        TRAVERSE has_task -> Task
        WHERE Task.status != 'done'
        AGGREGATE COUNT(*) AS remaining_tasks
    SELECT name, end_date, remaining_tasks, priority
    HAVING remaining_tasks > 0
    ORDER BY end_date ASC
""")

print("\n=== At-Risk Projects ===")
for row in at_risk:
    print(f"  {row.name}: {row.remaining_tasks} tasks remaining, "
          f"due {row.end_date}")

#Key Takeaways

  1. OQL is Ontology-centric: Queries target objects and relations, not tables and rows, making business semantics more intuitive
  2. TRAVERSE replaces JOIN: Graph traversal is OQL's core advantage; multi-level relation queries need no complex JOINs
  3. Built-in security: ABAC permission policies are automatically injected into queries
  4. Reasoning integration: The INFERRED keyword seamlessly connects to Intelligence Layer's reasoning engine
  5. Parameterized injection prevention: Always use parameterized queries to prevent OQL injection attacks
  6. Performance first: Use EXPLAIN, select only needed fields, and avoid N+1 queries

#Next Article

Next: S12-07 Pipeline Development Guide — Learn how to build end-to-end data pipelines, from data ingestion to Ontology write-back.

Tags: OQL Query Language Ontology Graph Traversal Aggregation Reasoning Query coomia-dip