ISO GQL Guide

November 25, 2025 · View on GitHub

Comprehensive set of queries for learning ISO GQL core features.

Table of Contents

  1. Setup: Schema and Graph Creation
  2. Data Insertion
  3. Property Updates with SET
  4. CALL and YIELD
  5. Simple Pattern Matching
  6. Pattern Matching with WHERE and RETURN
  7. NEXT Clause
  8. String and Date/Time Functions
  9. ORDER BY Clause
  10. GROUP BY and HAVING

Prerequisites

Start the GraphLite REPL:

# If installed globally
graphlite gql --path ./test_db -u admin -p admin

# Or run from build directory
./target/release/graphlite gql --path ./test_db -u admin -p admin

1. Setup: Schema and Graph Creation

1.1 Create Schema

-- Create a new schema for testing
CREATE SCHEMA /test_schema;

Expected Output: Success message

1.2 Set Session Schema

-- Set the session to use this schema
SESSION SET SCHEMA /test_schema;

Expected Output: Schema context updated

1.3 Create Graph

-- Create a graph within the schema
CREATE GRAPH /test_schema/social_network;

Expected Output: Graph created successfully

1.4 Set Session Graph

-- Set the session to use this graph
SESSION SET GRAPH /test_schema/social_network;

Expected Output: Graph context updated

1.5 Verify Context

-- Check current session settings
CALL gql.show_session();

Expected Output: Shows current schema and graph context


2. Data Insertion - Complete Script (Copy-Paste Ready)

2.1 All Data Insertion Commands

Copy and paste this entire block into the REPL after setting the session graph:

-- ============================================
-- COMPLETE DATA INSERTION SCRIPT
-- Copy-paste this entire block into GraphLite REPL
-- ============================================

-- Insert Person nodes (multiple nodes in one INSERT statement)
INSERT (:Person {name: 'Alice Johnson', age: 30, email: 'alice@example.com', city: 'New York', joined: '2020-01-15', status: 'active'}),
       (:Person {name: 'Bob Smith', age: 25, email: 'bob@example.com', city: 'San Francisco', joined: '2021-03-20', status: 'active'}),
       (:Person {name: 'Carol Williams', age: 28, email: 'carol@example.com', city: 'New York', joined: '2020-06-10', status: 'active'}),
       (:Person {name: 'David Brown', age: 35, email: 'david@example.com', city: 'Chicago', joined: '2019-11-05', status: 'inactive'}),
       (:Person {name: 'Eve Davis', age: 27, email: 'eve@example.com', city: 'San Francisco', joined: '2021-08-12', status: 'active'}),
       (:Person {name: 'Frank Miller', age: 32, email: 'frank@example.com', city: 'Boston', joined: '2020-04-18', status: 'active'});

-- Insert Company nodes
INSERT (:Company {name: 'TechCorp', industry: 'Technology', founded: '2010-01-01', employees: 500, revenue: 50000000}),
       (:Company {name: 'DataInc', industry: 'Analytics', founded: '2015-06-15', employees: 200, revenue: 20000000}),
       (:Company {name: 'CloudSystems', industry: 'Cloud Services', founded: '2012-03-10', employees: 800, revenue: 100000000});

-- Insert Project nodes
INSERT (:Project {name: 'AI Platform', budget: 5000000, start_date: '2023-01-01', status: 'active', priority: 'high'}),
       (:Project {name: 'Mobile App', budget: 2000000, start_date: '2023-03-15', status: 'active', priority: 'medium'}),
       (:Project {name: 'Data Pipeline', budget: 3000000, start_date: '2022-09-01', status: 'completed', priority: 'high'}),
       (:Project {name: 'Security Audit', budget: 500000, start_date: '2023-06-01', status: 'planned', priority: 'low'});

-- Create KNOWS relationships
MATCH (alice:Person {name: 'Alice Johnson'}), (bob:Person {name: 'Bob Smith'}) INSERT (alice)-[:KNOWS {since: '2020-05-10', strength: 'strong'}]->(bob);
MATCH (alice:Person {name: 'Alice Johnson'}), (carol:Person {name: 'Carol Williams'}) INSERT (alice)-[:KNOWS {since: '2020-02-14', strength: 'strong'}]->(carol);
MATCH (bob:Person {name: 'Bob Smith'}), (eve:Person {name: 'Eve Davis'}) INSERT (bob)-[:KNOWS {since: '2021-04-20', strength: 'medium'}]->(eve);
MATCH (carol:Person {name: 'Carol Williams'}), (david:Person {name: 'David Brown'}) INSERT (carol)-[:KNOWS {since: '2019-12-01', strength: 'weak'}]->(david);
MATCH (david:Person {name: 'David Brown'}), (frank:Person {name: 'Frank Miller'}) INSERT (david)-[:KNOWS {since: '2020-01-10', strength: 'medium'}]->(frank);
MATCH (eve:Person {name: 'Eve Davis'}), (frank:Person {name: 'Frank Miller'}) INSERT (eve)-[:KNOWS {since: '2021-09-05', strength: 'strong'}]->(frank);
MATCH (frank:Person {name: 'Frank Miller'}), (alice:Person {name: 'Alice Johnson'}) INSERT (frank)-[:KNOWS {since: '2020-07-22', strength: 'medium'}]->(alice);

-- Create WORKS_AT relationships
MATCH (alice:Person {name: 'Alice Johnson'}), (tech:Company {name: 'TechCorp'}) INSERT (alice)-[:WORKS_AT {role: 'Senior Engineer', since: '2020-02-01', salary: 120000}]->(tech);
MATCH (bob:Person {name: 'Bob Smith'}), (tech:Company {name: 'TechCorp'}) INSERT (bob)-[:WORKS_AT {role: 'Product Manager', since: '2021-04-01', salary: 110000}]->(tech);
MATCH (carol:Person {name: 'Carol Williams'}), (data:Company {name: 'DataInc'}) INSERT (carol)-[:WORKS_AT {role: 'Data Analyst', since: '2020-07-01', salary: 95000}]->(data);
MATCH (david:Person {name: 'David Brown'}), (cloud:Company {name: 'CloudSystems'}) INSERT (david)-[:WORKS_AT {role: 'DevOps Lead', since: '2019-12-01', salary: 130000}]->(cloud);
MATCH (eve:Person {name: 'Eve Davis'}), (tech:Company {name: 'TechCorp'}) INSERT (eve)-[:WORKS_AT {role: 'UX Designer', since: '2021-09-01', salary: 100000}]->(tech);
MATCH (frank:Person {name: 'Frank Miller'}), (data:Company {name: 'DataInc'}) INSERT (frank)-[:WORKS_AT {role: 'Engineering Manager', since: '2020-05-01', salary: 140000}]->(data);

-- Create ASSIGNED_TO relationships
MATCH (alice:Person {name: 'Alice Johnson'}), (ai:Project {name: 'AI Platform'}) INSERT (alice)-[:ASSIGNED_TO {role: 'Tech Lead', allocation: 0.8, start_date: '2023-01-15'}]->(ai);
MATCH (bob:Person {name: 'Bob Smith'}), (mobile:Project {name: 'Mobile App'}) INSERT (bob)-[:ASSIGNED_TO {role: 'Product Owner', allocation: 1.0, start_date: '2023-03-15'}]->(mobile);
MATCH (carol:Person {name: 'Carol Williams'}), (pipeline:Project {name: 'Data Pipeline'}) INSERT (carol)-[:ASSIGNED_TO {role: 'Data Engineer', allocation: 0.5, start_date: '2022-09-01'}]->(pipeline);
MATCH (eve:Person {name: 'Eve Davis'}), (mobile:Project {name: 'Mobile App'}) INSERT (eve)-[:ASSIGNED_TO {role: 'UI/UX Lead', allocation: 0.6, start_date: '2023-03-20'}]->(mobile);
MATCH (frank:Person {name: 'Frank Miller'}), (ai:Project {name: 'AI Platform'}) INSERT (frank)-[:ASSIGNED_TO {role: 'Engineering Manager', allocation: 0.4, start_date: '2023-01-15'}]->(ai);

-- Create SPONSORS relationships
MATCH (tech:Company {name: 'TechCorp'}), (ai:Project {name: 'AI Platform'}) INSERT (tech)-[:SPONSORS {amount: 3000000, percentage: 60}]->(ai);
MATCH (data:Company {name: 'DataInc'}), (pipeline:Project {name: 'Data Pipeline'}) INSERT (data)-[:SPONSORS {amount: 2500000, percentage: 83}]->(pipeline);
MATCH (cloud:Company {name: 'CloudSystems'}), (mobile:Project {name: 'Mobile App'}) INSERT (cloud)-[:SPONSORS {amount: 1500000, percentage: 75}]->(mobile);
MATCH (tech:Company {name: 'TechCorp'}), (security:Project {name: 'Security Audit'}) INSERT (tech)-[:SPONSORS {amount: 500000, percentage: 100}]->(security);

Expected Output:

  • 6 Person nodes created
  • 3 Company nodes created
  • 4 Project nodes created
  • 7 KNOWS relationships created
  • 6 WORKS_AT relationships created
  • 5 ASSIGNED_TO relationships created
  • 4 SPONSORS relationships created
  • Total: 13 nodes, 22 relationships

2.2 Verify Data Insertion

-- Count nodes by label
MATCH (p:Person) RETURN COUNT(p) AS person_count;
MATCH (c:Company) RETURN COUNT(c) AS company_count;
MATCH (proj:Project) RETURN COUNT(proj) AS project_count;

-- Count relationships by type
MATCH ()-[r:KNOWS]->() RETURN COUNT(r) AS knows_count;
MATCH ()-[r:WORKS_AT]->() RETURN COUNT(r) AS works_at_count;
MATCH ()-[r:ASSIGNED_TO]->() RETURN COUNT(r) AS assigned_to_count;
MATCH ()-[r:SPONSORS]->() RETURN COUNT(r) AS sponsors_count;

Expected Output:

  • person_count: 6
  • company_count: 3
  • project_count: 4
  • knows_count: 7
  • works_at_count: 6
  • assigned_to_count: 5
  • sponsors_count: 4

3. Property Updates with SET

3.1 Update Node Properties Using SET

-- Update single property
MATCH (p:Person {name: 'Alice Johnson'})
SET p.age = 31;

Expected Output: 1 property updated

-- Update multiple properties
MATCH (p:Person {name: 'Bob Smith'})
SET p.age = 26, p.status = 'premium';

Expected Output: 2 properties updated

-- Add new property
MATCH (p:Person {name: 'Carol Williams'})
SET p.phone = '+1-555-0123';

Expected Output: 1 property added

3.2 Update Relationship Properties Using MATCH-SET

-- Update relationship property
MATCH (alice:Person {name: 'Alice Johnson'})-[r:KNOWS]->(bob:Person {name: 'Bob Smith'})
SET r.strength = 'very strong', r.last_contact = '2023-12-01';

Expected Output: 2 properties updated

-- Update salary for work relationship
MATCH (carol:Person {name: 'Carol Williams'})-[r:WORKS_AT]->(c:Company)
SET r.salary = 100000, r.promoted = 'yes';

Expected Output: 2 properties updated

3.3 Verify Updates

-- Verify person updates
MATCH (p:Person {name: 'Alice Johnson'})
RETURN p.name, p.age, p.status;

MATCH (p:Person {name: 'Carol Williams'})
RETURN p.name, p.age, p.phone;

-- Verify relationship updates
MATCH (alice:Person {name: 'Alice Johnson'})-[r:KNOWS]->(bob:Person)
RETURN alice.name, bob.name, r.strength, r.last_contact;

Expected Output: Updated values should be reflected


4. CALL and YIELD

4.1 List Schemas

-- Call system procedure to list all schemas
CALL gql.list_schemas();

Expected Output: List of schemas including /test_schema

4.2 List Graphs

-- List all graphs in current schema
CALL gql.list_graphs();

Expected Output: List including /test_schema/social_network

4.3 Describe Schema

-- Get schema details
CALL gql.describe_schema('/test_schema');

Expected Output: Schema metadata

4.4 Describe Graph

-- Get graph details
CALL gql.describe_graph('/test_schema/social_network');

Expected Output: Graph metadata including node/edge counts

4.5 Cache Statistics

-- Get cache performance stats
CALL gql.cache_stats();

Expected Output: Cache hit rates, sizes, and statistics

4.6 Show Session

-- Display current session information
CALL gql.show_session();

Expected Output: Current user, schema, graph, permissions


5. Simple Pattern Matching

5.1 Match All Nodes of a Type

-- Find all people
MATCH (p:Person)
RETURN p.name, p.age, p.city;

Expected Output: 6 rows with person details

-- Find all companies
MATCH (c:Company)
RETURN c.name, c.industry, c.employees;

Expected Output: 3 rows with company details

5.2 Match Specific Node Properties

-- Find person by name
MATCH (p:Person {name: 'Alice Johnson'})
RETURN p.name, p.age, p.email;

Expected Output: 1 row with Alice's details

-- Find people in New York
MATCH (p:Person {city: 'New York'})
RETURN p.name, p.age;

Expected Output: 2 rows (Alice and Carol)

5.3 Match Simple Relationship Patterns

-- Find who Alice knows
MATCH (alice:Person {name: 'Alice Johnson'})-[:KNOWS]->(friend)
RETURN friend.name;

Expected Output: 2 rows (Bob and Carol)

-- Find where people work
MATCH (p:Person)-[:WORKS_AT]->(c:Company)
RETURN p.name, c.name;

Expected Output: 6 rows showing person-company pairs

-- Find project assignments
MATCH (p:Person)-[:ASSIGNED_TO]->(proj:Project)
RETURN p.name AS person, proj.name AS project;

Expected Output: 5 rows showing assignments

5.4 Match with Relationship Properties

-- Find strong friendships
MATCH (p1:Person)-[r:KNOWS {strength: 'strong'}]->(p2:Person)
RETURN p1.name, p2.name, r.since;

Expected Output: 3 rows with strong relationships

-- Find high-salary positions
MATCH (p:Person)-[r:WORKS_AT]->(c:Company)
WHERE r.salary > 110000
RETURN p.name, c.name, r.salary, r.role;

Expected Output: 3 rows (Alice, David, Frank)


6. Pattern Matching with WHERE and RETURN

6.1 Simple WHERE Conditions

-- Find people older than 28
MATCH (p:Person)
WHERE p.age > 28
RETURN p.name, p.age
ORDER BY p.age;

Expected Output: 4 rows (Alice: 30, Frank: 32, David: 35, and Carol if age > 28)

-- Find active people in specific cities
MATCH (p:Person)
WHERE p.city = 'New York' AND p.status = 'active'
RETURN p.name, p.city, p.status;

Expected Output: 2 rows (Alice and Carol)

-- Find companies with more than 300 employees
MATCH (c:Company)
WHERE c.employees > 300
RETURN c.name, c.employees, c.revenue;

Expected Output: 2 rows (TechCorp and CloudSystems)

6.2 OR Patterns in WHERE

-- Find people in San Francisco OR Chicago
MATCH (p:Person)
WHERE p.city = 'San Francisco' OR p.city = 'Chicago'
RETURN p.name, p.city;

Expected Output: 3 rows (Bob, Eve, David)

-- Find high-priority or completed projects
MATCH (proj:Project)
WHERE proj.priority = 'high' OR proj.status = 'completed'
RETURN proj.name, proj.priority, proj.status;

Expected Output: 3 rows (AI Platform, Data Pipeline, and any high priority projects)

6.3 AND/OR Combined Patterns

-- Find active people who are young OR in New York
MATCH (p:Person)
WHERE p.status = 'active' AND (p.age < 30 OR p.city = 'New York')
RETURN p.name, p.age, p.city, p.status;

Expected Output: 4 rows (Alice, Bob, Carol, Eve)

-- Find tech or analytics companies with high revenue
MATCH (c:Company)
WHERE (c.industry = 'Technology' OR c.industry = 'Analytics')
  AND c.revenue > 30000000
RETURN c.name, c.industry, c.revenue;

Expected Output: 1-2 rows (TechCorp and possibly CloudSystems)

6.4 Complex Relationship Patterns with WHERE

-- Find people who know someone in San Francisco
MATCH (p1:Person)-[:KNOWS]->(p2:Person)
WHERE p2.city = 'San Francisco'
RETURN p1.name AS person, p2.name AS friend_in_sf, p2.city;

Expected Output: 2 rows (Alice→Bob, Bob→Eve)

-- Find coworkers at TechCorp
MATCH (p1:Person)-[:WORKS_AT]->(c:Company {name: 'TechCorp'}),
      (p2:Person)-[:WORKS_AT]->(c)
WHERE p1.name < p2.name
RETURN p1.name, p2.name, c.name AS company;

Expected Output: 3 rows (Alice-Bob, Alice-Eve, Bob-Eve)


7. NEXT Clause

7.1 Basic NEXT Usage

-- Find friends of friends
MATCH (person:Person {name: 'Alice Johnson'})-[:KNOWS]->(friend)
NEXT MATCH (friend)-[:KNOWS]->(fof)
RETURN person.name AS start, friend.name AS intermediate, fof.name AS friend_of_friend;

Expected Output: Rows showing 2-hop paths from Alice

-- Find company through person
MATCH (p:Person {name: 'Bob Smith'})
NEXT MATCH (p)-[:WORKS_AT]->(c:Company)
RETURN p.name, c.name AS company, c.industry;

Expected Output: 1 row (Bob → TechCorp)

7.2 Multi-hop Patterns with NEXT

-- Find people → company → project path
MATCH (p:Person {name: 'Alice Johnson'})-[:WORKS_AT]->(c:Company)
NEXT MATCH (c)-[:SPONSORS]->(proj:Project)
RETURN p.name AS person, c.name AS company, proj.name AS project;

Expected Output: Rows showing Alice's company's sponsored projects

-- Three-hop: person → knows → works_at → company
MATCH (p1:Person {name: 'Alice Johnson'})-[:KNOWS]->(p2:Person)
NEXT MATCH (p2)-[:WORKS_AT]->(c:Company)
RETURN p1.name, p2.name, c.name AS company;

Expected Output: Alice's friends and where they work

7.3 NEXT with WHERE Clause

-- Find friends working at high-revenue companies
MATCH (p1:Person {name: 'Alice Johnson'})-[:KNOWS]->(p2:Person)
NEXT MATCH (p2)-[:WORKS_AT]->(c:Company)
WHERE c.revenue > 50000000
RETURN p1.name, p2.name, c.name, c.revenue;

Expected Output: Alice's friends at high-revenue companies

-- Find project paths with allocation filter
MATCH (p:Person)-[:ASSIGNED_TO]->(proj:Project)
WHERE proj.status = 'active'
NEXT MATCH (c:Company)-[:SPONSORS]->(proj)
WHERE c.employees > 300
RETURN p.name, proj.name, c.name;

Expected Output: Active projects with large company sponsors


8. String and Date/Time Functions

8.1 String Functions

-- Convert names to uppercase
MATCH (p:Person)
RETURN p.name, upper(p.name) AS name_upper;

Expected Output: 6 rows with uppercase names

-- Convert to lowercase and extract substring
MATCH (p:Person)
RETURN p.name,
       lower(p.name) AS name_lower,
       substring(p.name, 0, 5) AS first_5_chars;

Expected Output: 6 rows with lowercase and substrings

-- Trim and replace operations
MATCH (c:Company)
RETURN c.name,
       trim(c.name) AS trimmed,
       replace(c.name, 'Inc', 'Incorporated') AS replaced;

Expected Output: 3 rows with string transformations

-- String concatenation in WHERE
MATCH (p:Person)
WHERE lower(p.email) LIKE '%example.com%'
RETURN p.name, p.email;

Expected Output: All 6 people (all have @example.com)

8.2 Date/Time Functions

-- Create duration values
MATCH (p:Person)
RETURN p.name,
       p.joined,
       duration('P1Y') AS one_year;

Expected Output: 6 rows with duration

-- Calculate tenure using duration
MATCH (p:Person)-[r:WORKS_AT]->(c:Company)
RETURN p.name,
       c.name,
       r.since,
       duration('P3Y') AS three_years;

Expected Output: 6 rows with work tenure information

-- Filter by date ranges
MATCH (p:Person)
WHERE p.joined > '2020-01-01' AND p.joined < '2021-12-31'
RETURN p.name, p.joined
ORDER BY p.joined;

Expected Output: People who joined between 2020-2021

8.3 Combined String and Date Functions

-- Format output with string and date functions
MATCH (p:Person)-[:WORKS_AT]->(c:Company)
RETURN upper(p.name) AS name,
       lower(c.industry) AS industry,
       substring(p.email, 0, 10) AS email_preview;

Expected Output: 6 rows with formatted data

-- Complex filtering with functions
MATCH (p:Person)
WHERE upper(p.city) = 'NEW YORK'
  AND p.joined > '2020-01-01'
RETURN p.name, p.city, p.joined;

Expected Output: New York residents who joined after 2020


9. ORDER BY Clause

9.1 Simple ORDER BY

-- Order by age ascending
MATCH (p:Person)
RETURN p.name, p.age
ORDER BY p.age;

Expected Output: 6 rows sorted by age (youngest first)

-- Order by age descending
MATCH (p:Person)
RETURN p.name, p.age
ORDER BY p.age DESC;

Expected Output: 6 rows sorted by age (oldest first)

-- Order by string property
MATCH (c:Company)
RETURN c.name, c.employees
ORDER BY c.name;

Expected Output: 3 companies alphabetically sorted

9.2 Multiple ORDER BY Columns

-- Order by city, then by age
MATCH (p:Person)
RETURN p.name, p.city, p.age
ORDER BY p.city, p.age;

Expected Output: 6 rows sorted by city first, then age within each city

-- Order by status descending, then name ascending
MATCH (p:Person)
RETURN p.name, p.status, p.age
ORDER BY p.status DESC, p.name;

Expected Output: Active people first, then inactive, alphabetically within each group

9.3 ORDER BY with Expressions

-- Order by salary from relationship
MATCH (p:Person)-[r:WORKS_AT]->(c:Company)
RETURN p.name, c.name, r.salary
ORDER BY r.salary DESC;

Expected Output: 6 rows sorted by salary (highest first)

-- Order by computed values
MATCH (c:Company)
RETURN c.name, c.employees, c.revenue, c.revenue / c.employees AS revenue_per_employee
ORDER BY revenue_per_employee DESC;

Expected Output: 3 companies sorted by revenue per employee

9.4 ORDER BY with LIMIT

-- Top 3 oldest people
MATCH (p:Person)
RETURN p.name, p.age
ORDER BY p.age DESC
LIMIT 3;

Expected Output: 3 rows (David, Frank, Alice)

-- Top 2 highest-paid employees
MATCH (p:Person)-[r:WORKS_AT]->(c:Company)
RETURN p.name, c.name, r.salary
ORDER BY r.salary DESC
LIMIT 2;

Expected Output: 2 highest salaries


10. GROUP BY and HAVING

10.1 Basic GROUP BY

-- Count people per city
MATCH (p:Person)
RETURN p.city, COUNT(p) AS person_count
GROUP BY p.city;

Expected Output: 4-5 rows (one per city with counts)

-- Average age per city
MATCH (p:Person)
RETURN p.city, AVG(p.age) AS avg_age, COUNT(p) AS population
GROUP BY p.city;

Expected Output: City-wise statistics

-- Count employees per company
MATCH (p:Person)-[:WORKS_AT]->(c:Company)
RETURN c.name, COUNT(p) AS employee_count
GROUP BY c.name;

Expected Output: 3 rows (TechCorp: 3, DataInc: 2, CloudSystems: 1)

10.2 GROUP BY with Aggregations

-- Min, Max, Average age per city
MATCH (p:Person)
RETURN p.city,
       MIN(p.age) AS min_age,
       MAX(p.age) AS max_age,
       AVG(p.age) AS avg_age,
       COUNT(p) AS count
GROUP BY p.city;

Expected Output: Comprehensive city statistics

-- Salary statistics per company
MATCH (p:Person)-[r:WORKS_AT]->(c:Company)
RETURN c.name,
       MIN(r.salary) AS min_salary,
       MAX(r.salary) AS max_salary,
       AVG(r.salary) AS avg_salary,
       COUNT(p) AS employee_count
GROUP BY c.name;

Expected Output: Salary stats for each company

10.3 HAVING Clause

-- Cities with more than 1 person
MATCH (p:Person)
RETURN p.city, COUNT(p) AS person_count
GROUP BY p.city
HAVING COUNT(p) > 1;

Expected Output: Only cities with 2+ people (New York, San Francisco)

-- Companies with average salary above 105,000
MATCH (p:Person)-[r:WORKS_AT]->(c:Company)
RETURN c.name, AVG(r.salary) AS avg_salary, COUNT(p) AS employee_count
GROUP BY c.name
HAVING AVG(r.salary) > 105000;

Expected Output: Companies meeting salary threshold

-- Cities with high average age (>28)
MATCH (p:Person)
RETURN p.city, AVG(p.age) AS avg_age, COUNT(p) AS population
GROUP BY p.city
HAVING AVG(p.age) > 28;

Expected Output: Cities with older populations

10.4 GROUP BY with ORDER BY

-- Cities ranked by population
MATCH (p:Person)
RETURN p.city, COUNT(p) AS population
GROUP BY p.city
ORDER BY population DESC;

Expected Output: Cities sorted by person count

-- Companies ranked by average salary
MATCH (p:Person)-[r:WORKS_AT]->(c:Company)
RETURN c.name,
       AVG(r.salary) AS avg_salary,
       COUNT(p) AS employees
GROUP BY c.name
ORDER BY avg_salary DESC;

Expected Output: Companies sorted by average salary

10.5 Complex GROUP BY with HAVING and ORDER BY

-- Status groups with statistics, filtered and sorted
MATCH (p:Person)
RETURN p.status,
       COUNT(p) AS count,
       AVG(p.age) AS avg_age,
       MIN(p.age) AS min_age,
       MAX(p.age) AS max_age
GROUP BY p.status
HAVING COUNT(p) >= 2
ORDER BY avg_age DESC;

Expected Output: Status groups meeting criteria, sorted by age

-- Project priority with funding stats
MATCH (c:Company)-[r:SPONSORS]->(proj:Project)
RETURN proj.priority,
       COUNT(proj) AS project_count,
       SUM(r.amount) AS total_funding,
       AVG(r.amount) AS avg_funding
GROUP BY proj.priority
HAVING SUM(r.amount) > 1000000
ORDER BY total_funding DESC;

Expected Output: Priority groups with significant funding


Additional Test Scenarios

Multi-hop Relationship Queries

-- Find colleagues (people working at same company)
MATCH (p1:Person)-[:WORKS_AT]->(c:Company),
      (p2:Person)-[:WORKS_AT]->(c)
WHERE p1.name < p2.name
RETURN p1.name AS person1, p2.name AS person2, c.name AS company;

Expected Output: Colleague pairs at each company

-- Find people working on same project
MATCH (p1:Person)-[:ASSIGNED_TO]->(proj:Project),
      (p2:Person)-[:ASSIGNED_TO]->(proj)
WHERE p1.name < p2.name
RETURN p1.name, p2.name, proj.name;

Expected Output: Team members on shared projects

Combined Features Query

-- Complex query combining multiple features
MATCH (p:Person)-[w:WORKS_AT]->(c:Company)
WHERE p.age > 25 AND w.salary > 100000
RETURN upper(p.name) AS name,
       p.age,
       c.name AS company,
       w.salary,
       w.role
ORDER BY w.salary DESC, p.age
LIMIT 5;

Expected Output: Top 5 high earners with formatted output

-- Group by with string functions and having
MATCH (p:Person)-[:WORKS_AT]->(c:Company)
RETURN upper(substring(c.industry, 0, 4)) AS industry_code,
       COUNT(p) AS workers,
       AVG(p.age) AS avg_age
GROUP BY c.industry
HAVING COUNT(p) >= 2
ORDER BY workers DESC;

Expected Output: Industry statistics for categories with 2+ workers


Cleanup

Remove Test Data (Optional)

-- Delete all relationships first
MATCH ()-[r]->()
DELETE r;

-- Then delete all nodes
MATCH (n)
DELETE n;

-- Drop graph
DROP GRAPH /test_schema/social_network;

-- Drop schema
DROP SCHEMA /test_schema;

Notes

  • All queries assume you're in the GraphLite REPL with the session context set
  • Query execution times will vary based on system performance
  • Some queries may need adjustment based on actual data inserted
  • If any query fails, check the error message and verify prerequisites
  • Use CALL gql.show_session(); to verify context at any time

Troubleshooting

If queries fail with "No graph context":

SESSION SET GRAPH /test_schema/social_network;

If data isn't found:

-- Verify data exists
MATCH (n) RETURN COUNT(n) AS total_nodes;
MATCH ()-[r]->() RETURN COUNT(r) AS total_relationships;

To reset and start over:

-- See cleanup section above

End of GQL Guide Last Updated: November 2025