• Home
  • Project
    Introduction
    • Introduction
    • Background and Motivation
    • What is a Good Timetable?
    • Project Aims and Scope
  • Graph Data
    Model
    • Graph vs Relational Data Models
    • Graph Data Model for Timetabling
    • Early Insights
    • Model Expansion
    • Graphing Time
  • Data
    Pipeline
    • ETL Overview
    • Approach
    • Configuration and Logging
    • Extract
    • Transform
    • Google Drive Load
    • Neo4j Load
    • Reflection
  • Timetable
    Metrics
    • Timetable Metrics
    • Metric Aggregations
    • Implementing Metrics
    • TQI Summary
  • Final
    Thoughts
  • Appendices
    & Extras
    • Appendix Table of Contents
    • References
    • Acknowledgements
  • Word
  1. Appendices
  2. Neo4j & Cypher Code
  3. Cypher Queries
  • Home
  • Project Introduction
    • Introduction
    • Background and Motivation
    • What is a Good Timetable?
    • Project Aims and Scope
  • Graph Data Model
    • Graph vs Relational Data Models
    • Graph Data Model for Timetabling
    • Early Insights
    • Model Expansion
    • Graphing Time
  • Data Pipeline
    • ETL Overview
    • Approach
    • Configuration and Logging
    • Extract
    • Transform
    • Google Drive Load
    • Neo4j Load
    • Reflection
  • Timetable Metrics
    • Timetable Metrics
    • Metric Aggregations
    • Implementing Metrics
    • TQI Summary
  • Final Thoughts
  • Appendices
    • Random Graph Generator
    • Technology Stack
    • Configuration
    • Anonymisation
    • ETL Summary and Code
      • ETL Summary
      • ETL Code
      • Config and Misc
      • Extract-SQL
      • Extract
      • Google Drive Load
      • Transform
      • Neo4j Load
    • Neo4j & Cypher Code
      • Cypher Queries
      • Creating Nodes and Relationships
      • Deleting Nodes and Relationships
      • General Queries
      • Count Queries
      • Hard (timetabling) Constraints
      • Student Clashes
      • Soft Constraints
      • Rooms and Spaces
      • Perspectives
      • Blue Skies Opportunities
  • Supervision
    • Supervision
    • Notes Example 1
    • Notes Example 2
    • Notes Example 3
  • References
  • Acknowledgements

On this page

  • Constraints
  • Indexes
    • Creating Indexes
  1. Appendices
  2. Neo4j & Cypher Code
  3. Cypher Queries

M: Cypher Queries


These pages collate Cypher1 queries used in the development of this project. The queries are grouped by the type of operation they perform, such as creating nodes, relationships, or querying the graph. The queries are presented in a format that can be copied and pasted directly into a Neo4j browser or other Cypher-compatible interface.

They represent a starting point for further exploration and development of the graph database. The queries are not exhaustive, and there are many more possibilities for querying and analysing the data.

Constraints

Constraints in Neo4j are used to enforce rules on the graph data, such as ensuring that certain properties are unique or that nodes have specific properties. Constraints can be used to maintain data integrity and prevent duplicate or inconsistent data. For example, we would want to enforce uniqueness constraints on most nodes and relationships, so that we do not duplicate students or allocations, etc.

Constraints

Indexes

Indexes in Neo4j are used to speed up queries by allowing the database to quickly locate nodes or relationships based on a property value. They will depend heavily on graph structure and specific use-cases. For example, if performing regular searches on (activity{actStartTime}) it is probably beneficial to create an index on this property.

Search performance indexes include RANGE, FULLTEXT, and POINT. Range indexes are the default and support most queries. Text indexes, like FULLTEXT, are used for string-based searches and optimised for queries containing operators like CONTAINS or STARTS WITH. Point indexes are used for spatial queries and are optimised for latitude and longitude properties.

Indexes in Graph

Click to show code
from connect_to_neo4j_db import connect_to_neo4j
from neo4j import GraphDatabase

# connect to Neo4j
driver = connect_to_neo4j()

# session
session = driver.session()

# run query
query = """
SHOW INDEXES;
"""
print("Running query...\n")
result = session.run(query)
for record in result:
    print(record)
Connecting to Neo4j database....
Connected to Neo4j database successfully! Driver: <neo4j._sync.driver.Neo4jDriver object at 0x000001F64DDB4DD0>
Running query...

<Record id=7 name='activity_clash_index' state='ONLINE' populationPercent=100.0 type='RANGE' entityType='NODE' labelsOrTypes=['activity'] properties=['actStartDate', 'actStartTime', 'actEndTime'] indexProvider='range-1.0' owningConstraint=None lastRead=None readCount=0>
<Record id=19 name='graphid_demoRoom_uniq' state='ONLINE' populationPercent=100.0 type='RANGE' entityType='NODE' labelsOrTypes=['demoRoom'] properties=['graphid'] indexProvider='range-1.0' owningConstraint='graphid_demoRoom_uniq' lastRead=neo4j.time.DateTime(2024, 8, 20, 18, 16, 44, 231000000, tzinfo=<UTC>) readCount=3>
<Record id=4 name='index_12b79beb' state='ONLINE' populationPercent=100.0 type='RANGE' entityType='NODE' labelsOrTypes=['activity'] properties=['actEndTime'] indexProvider='range-1.0' owningConstraint=None lastRead=None readCount=0>
<Record id=6 name='index_207d313' state='ONLINE' populationPercent=100.0 type='RANGE' entityType='NODE' labelsOrTypes=['activity'] properties=['id'] indexProvider='range-1.0' owningConstraint=None lastRead=None readCount=0>
<Record id=8 name='index_241bd22f' state='ONLINE' populationPercent=100.0 type='RANGE' entityType='NODE' labelsOrTypes=['room'] properties=['roomName'] indexProvider='range-1.0' owningConstraint=None lastRead=neo4j.time.DateTime(2024, 8, 22, 12, 32, 5, 744000000, tzinfo=<UTC>) readCount=154>
<Record id=9 name='index_2d375d70' state='ONLINE' populationPercent=100.0 type='RANGE' entityType='NODE' labelsOrTypes=['room'] properties=['roomLatitude'] indexProvider='range-1.0' owningConstraint=None lastRead=neo4j.time.DateTime(2024, 8, 15, 18, 40, 6, 645000000, tzinfo=<UTC>) readCount=107>
<Record id=0 name='index_343aff4e' state='ONLINE' populationPercent=100.0 type='LOOKUP' entityType='NODE' labelsOrTypes=None properties=None indexProvider='token-lookup-1.0' owningConstraint=None lastRead=neo4j.time.DateTime(2024, 8, 22, 12, 32, 20, 867000000, tzinfo=<UTC>) readCount=117852>
<Record id=10 name='index_43c5c824' state='ONLINE' populationPercent=100.0 type='RANGE' entityType='NODE' labelsOrTypes=['room'] properties=['roomLongitude'] indexProvider='range-1.0' owningConstraint=None lastRead=neo4j.time.DateTime(2024, 8, 15, 18, 40, 6, 646000000, tzinfo=<UTC>) readCount=106>
<Record id=2 name='index_6acb9a84' state='ONLINE' populationPercent=100.0 type='RANGE' entityType='NODE' labelsOrTypes=['activity'] properties=['actStartDate'] indexProvider='range-1.0' owningConstraint=None lastRead=neo4j.time.DateTime(2024, 8, 22, 12, 32, 22, 268000000, tzinfo=<UTC>) readCount=117>
<Record id=5 name='index_7ade165f' state='ONLINE' populationPercent=100.0 type='RANGE' entityType='NODE' labelsOrTypes=['activity'] properties=['actModSplusID'] indexProvider='range-1.0' owningConstraint=None lastRead=neo4j.time.DateTime(2024, 8, 15, 18, 40, 6, 638000000, tzinfo=<UTC>) readCount=148>
<Record id=1 name='index_f7700477' state='ONLINE' populationPercent=100.0 type='LOOKUP' entityType='RELATIONSHIP' labelsOrTypes=None properties=None indexProvider='token-lookup-1.0' owningConstraint=None lastRead=neo4j.time.DateTime(2024, 8, 15, 13, 53, 33, 557000000, tzinfo=<UTC>) readCount=134>
<Record id=3 name='index_f86013e' state='ONLINE' populationPercent=100.0 type='RANGE' entityType='NODE' labelsOrTypes=['activity'] properties=['actStartTime'] indexProvider='range-1.0' owningConstraint=None lastRead=neo4j.time.DateTime(2024, 8, 22, 12, 31, 56, 599000000, tzinfo=<UTC>) readCount=19>
<Record id=18 name='lat_demoRoom' state='ONLINE' populationPercent=100.0 type='RANGE' entityType='NODE' labelsOrTypes=['demoRoom'] properties=['lat'] indexProvider='range-1.0' owningConstraint=None lastRead=None readCount=0>
<Record id=17 name='lon_demoRoom' state='ONLINE' populationPercent=100.0 type='RANGE' entityType='NODE' labelsOrTypes=['demoRoom'] properties=['lon'] indexProvider='range-1.0' owningConstraint=None lastRead=None readCount=0>
<Record id=16 name='rm_cat_demoRoom' state='ONLINE' populationPercent=100.0 type='RANGE' entityType='NODE' labelsOrTypes=['demoRoom'] properties=['rm_cat'] indexProvider='range-1.0' owningConstraint=None lastRead=neo4j.time.DateTime(2024, 8, 20, 18, 16, 44, 250000000, tzinfo=<UTC>) readCount=3>
<Record id=15 name='rm_type_demoRoom' state='ONLINE' populationPercent=100.0 type='RANGE' entityType='NODE' labelsOrTypes=['demoRoom'] properties=['rm_type'] indexProvider='range-1.0' owningConstraint=None lastRead=neo4j.time.DateTime(2024, 8, 20, 18, 16, 44, 258000000, tzinfo=<UTC>) readCount=3>
<Record id=11 name='room_fulltext_index' state='ONLINE' populationPercent=100.0 type='FULLTEXT' entityType='NODE' labelsOrTypes=['room'] properties=['roomName', 'roomDescription', 'roomType', 'roomCapacity'] indexProvider='fulltext-1.0' owningConstraint=None lastRead=neo4j.time.DateTime(2024, 8, 20, 18, 16, 43, 786000000, tzinfo=<UTC>) readCount=99>
<Record id=12 name='room_geo_index' state='ONLINE' populationPercent=100.0 type='FULLTEXT' entityType='NODE' labelsOrTypes=['room'] properties=['roomLatitude', 'roomLongitude'] indexProvider='fulltext-1.0' owningConstraint=None lastRead=neo4j.time.DateTime(2024, 8, 20, 18, 16, 43, 803000000, tzinfo=<UTC>) readCount=12>

Creating Indexes

This is the general syntax for creating an INDEX and some examples.

// General syntax
CREATE INDEX FOR (n:NodeLabel) ON (n.propertyName)

// Examples
CREATE INDEX FOR (a:activity) ON (a.actStartDate);
CREATE INDEX FOR (a:activity) ON (a.actStartTime);
CREATE INDEX FOR (a:activity) ON (a.actEndTime);
CREATE INDEX FOR (a:activity) ON (a.actModSplusID);
CREATE INDEX FOR (a:activity) ON (a.id);
// composite index for clashes
CREATE INDEX activity_clash_index FOR (a:activity) ON (a.actStartDate, a.actStartTime, a.actEndTime);

CREATE INDEX FOR (r:room) ON (r.roomName);
CREATE INDEX FOR (r:room) ON (r.roomLatitude);
CREATE INDEX FOR (r:room) ON (r.roomLongitude);

CREATE SPATIAL INDEX room_location_index FOR (r:demoRoom) ON (r.location)
CREATE SPATIAL INDEX demoroom_location_index FOR (r:room) ON (r.location)

Footnotes

  1. “Cypher is a declarative graph query language that allows for expressive and efficient data querying in a property graph” (Wikipedia contributors, 2024)↩︎

Neo4j Load
Creating Nodes and Relationships

Copyright 2024, Petter Lövehagen

 

Built with Quarto