Skip to content

Latest commit

 

History

History
443 lines (343 loc) · 14.7 KB

File metadata and controls

443 lines (343 loc) · 14.7 KB

Schema Support in Knows

Knows supports custom graph schemas via JSON files, allowing you to define your own node and edge types with custom properties. GQL-inspired schema format (ISO/IEC 39075).

A JSON Schema is provided for validation and IDE autocompletion. To enable it, add "$schema" to your schema file:

{
    "$schema": "https://raw.githubusercontent.com/lszeremeta/knows/main/knows/schema.json",
    "nodeLabel": "MyNode",
    ...
}

Validating Your Schema

IDE Validation (recommended)

Most modern IDEs validate JSON Schema automatically when $schema is present:

  • VS Code: Built-in support, shows errors inline
  • JetBrains IDEs: Built-in support (PyCharm, IntelliJ, WebStorm)
  • Sublime Text: Use LSP or SublimeLinter-json plugin

Online Validators

Command Line

Using check-jsonschema (Python):

pip install check-jsonschema
check-jsonschema --schemafile schema.json my_schema.json

Using ajv-cli (Node.js):

npm install -g ajv-cli
ajv validate -s schema.json -d my_schema.json

Python

import json
from jsonschema import validate, ValidationError

with open('schema.json') as f:
    json_schema = json.load(f)

with open('my_schema.json') as f:
    my_schema = json.load(f)

try:
    validate(instance=my_schema, schema=json_schema)
    print("Schema is valid!")
except ValidationError as e:
    print(f"Validation error: {e.message}")

Quick Start

Create a schema file (e.g., my_schema.json):

{
    "nodeLabel": "Product",
    "edgeLabel": "relatedTo",
    "nodeProperties": {
        "name": "String",
        "price": {"type": "Float", "min": 0.99, "max": 999.99},
        "category": {"enum": ["Electronics", "Clothing", "Food"]}
    },
    "edgeProperties": {
        "similarity": {"type": "Float", "min": 0.0, "max": 1.0}
    }
}

Then generate a graph:

knows -n 20 -e 30 --schema my_schema.json

Schema Structure

A schema file is a JSON object with the following optional fields:

Field Type Default Description
nodeLabel string "Node" Label for all generated nodes
edgeLabel string "edge" Label for all generated edges
nodeProperties object {} Property definitions for nodes
edgeProperties object {} Property definitions for edges (supports symmetric)
computedNodeProperties object {} Properties computed from graph structure

Property Types

Properties can be defined in two ways:

Simple Type (string)

{
    "nodeProperties": {
        "name": "String",
        "age": "Int",
        "active": "Boolean"
    }
}

Complex Type (object with constraints)

{
    "nodeProperties": {
        "salary": {"type": "Int", "min": 30000, "max": 200000},
        "rating": {"type": "Float", "min": 0.0, "max": 5.0, "precision": 1},
        "status": {"enum": ["active", "inactive", "pending"]}
    }
}

Available Types

String Types

Type Description Example Output
String Random word "lorem"
Name Full name "John Smith"
FirstName First name "John"
LastName Last name "Smith"
FullName Full name (alias for Name) "Jane Doe"
Email Email address "john@example.com"
Phone Phone number "+1-555-123-4567"
Address Full address "123 Main St, City"
City City name "New York"
Country Country name "United States"
Company Company name "Acme Inc"
Job Job title "Software Engineer"
Text Paragraph of text Long text (configurable via maxLength)
Sentence Single sentence "Lorem ipsum dolor sit."
Paragraph Full paragraph Multiple sentences
Url URL "https://example.com"
Color Color name "blue"
Uuid UUID string "550e8400-e29b-41d4-a716-446655440000"

Numeric Types

Type Description Constraints
Int / Integer Integer number min, max (default: 0-10000)
Float Floating-point number min, max, precision (default: 0.0-1000.0, precision 2)
Double Double-precision float min, max, precision (default: 0.0-1000.0, precision 4)
Boolean / Bool Boolean value -

Date/Time Types

Type Description Constraints
Date ISO date string min, max (default: 1970-01-01 to 2025-12-31)
DateTime ISO datetime string min, max (default: -30 years to now)
Time Time string -
Year Year number min, max (default: 1950-2025)
Duration ISO 8601 duration string min, max (default: PT0S to P1Y)

Enum Type

Define a fixed set of possible values:

{
    "status": {"enum": ["pending", "approved", "rejected"]}
}

Type Constraints

For Numeric Types (Int, Float, Double)

  • min: Minimum value (inclusive)
  • max: Maximum value (inclusive)
  • precision: Decimal places (for Float and Double)
{
    "price": {"type": "Float", "min": 0.01, "max": 9999.99, "precision": 2}
}

For Date Types

  • min: Start date in ISO format (YYYY-MM-DD)
  • max: End date in ISO format (YYYY-MM-DD)
{
    "foundedDate": {"type": "Date", "min": "1900-01-01", "max": "2025-12-31"}
}

For Duration Type

Durations use the ISO 8601 duration format - the same notation Cypher's duration() accepts. A duration string starts with P ("period"); a T separates the date part (years/months/weeks/days) from the time part (hours/minutes/seconds):

Component Meaning Example
nY years P2Y = 2 years
nM (before T) months P3M = 3 months
nW weeks P2W = 2 weeks
nD days P10D = 10 days
nH (after T) hours PT5H = 5 hours
nM (after T) minutes PT30M = 30 minutes
nS (after T) seconds PT45S = 45 seconds

Components combine in order, e.g. P1Y2M10DT2H30M ("1 year, 2 months, 10 days, 2 hours, 30 minutes"). Generated values are ISO 8601 strings like P5DT3H20M; zero components are omitted and an empty duration is rendered as PT0S.

Constraints:

  • min: Minimum duration as an ISO 8601 duration string (default: PT0S)
  • max: Maximum duration as an ISO 8601 duration string (default: P1Y)

Examples:

{
    "uptime": "Duration",
    "warranty": {"type": "Duration", "min": "PT0S", "max": "P2Y"},
    "taskTime": {"type": "Duration", "min": "PT30M", "max": "PT8H"},
    "loanTerm": {"type": "Duration", "min": "P1Y", "max": "P30Y"}
}

The simple form ("uptime": "Duration") uses the default PT0S-P1Y range. Like other types, Duration can be marked symmetric on edges:

{
    "edgeProperties": {
        "totalCollaborationTime": {"type": "Duration", "min": "P7D", "max": "P3Y", "symmetric": true}
    }
}

Note: To draw a random value from the min-max range, durations are reduced to seconds using fixed calendar approximations (1 year = 365 days, 1 month = 30 days, 1 week = 7 days). This is sufficient for synthetic data. Weeks (nW) are accepted in min/max bounds but never appear in generated values - e.g. a P2W bound is treated as 14 days and a value of that length is rendered as P14D.

For Text Type

  • maxLength: Maximum number of characters (minimum: 5)
{
    "description": {"type": "Text", "maxLength": 500}
}

Type Aliases

GQL-style uppercase type names are supported as aliases:

Alias Maps To
STRING String
INTEGER Int
INT64 Int
UINT64 Int
FLOAT64 Float
BOOLEAN Boolean
BOOL Bool
DATE Date
DATETIME DateTime
ZONED DATETIME DateTime
DURATION Duration

Symmetric Edge Properties

Edge properties can be marked as symmetric to ensure edges in both directions (A→B and B→A) share the same value:

{
    "edgeProperties": {
        "meetingDate": {"type": "Date", "symmetric": true},
        "sharedProject": {"enum": ["Alpha", "Beta", "Gamma"], "symmetric": true}
    }
}

When an edge A→B is created and a reverse edge B→A already exists, symmetric properties are copied from the existing edge. This is useful for mutual relationships where both directions should have consistent values.

symmetric is only valid on edge properties - using it in nodeProperties is rejected during schema validation.

Computed Node Properties

Properties that are calculated from the graph structure after generation:

{
    "computedNodeProperties": {
        "connectionCount": "degree"
    }
}
Type Description
degree Total unique connections (undirected degree - counts both incoming and outgoing edges)

Computed properties are added to nodes after all edges are generated, ensuring accurate values based on the final graph topology.

Example Schemas

Ready-to-use example schemas are available in the schema-examples/ directory:

Simple (2-3 properties each)

File Description
simple_friendship_schema.json Person/friendOf - name, age
simple_task_schema.json Task/dependsOn - title, status
simple_webpage_schema.json Page/linksTo - url, title
simple_message_schema.json User/messaged - username, email

Real-world

File Description
default_schema.json Default Knows graph (Person/knows)
social_network_schema.json Social media users and followers
employee_schema.json Employee collaboration network
ecommerce_schema.json E-commerce product relationships
knowledge_graph_schema.json Knowledge graph with concepts
citation_network_schema.json Academic paper citations
transportation_schema.json Transit stations and routes
financial_schema.json Bank accounts and transactions
infrastructure_schema.json IT services and dependencies
movie_database_schema.json Actor co-starring relationships

Use them directly or as templates for your own schemas:

knows -n 50 -e 100 --schema schema-examples/social_network_schema.json
# or with Docker (using built-in example schemas)
docker run --rm lszeremeta/knows --schema /app/schema-examples/social_network_schema.json -n 50 -e 100

Usage Examples

Generate graph with custom schema

knows --schema my_schema.json
# or
docker run --rm -v "$(pwd)":/data lszeremeta/knows --schema /data/my_schema.json

Specify node and edge count

knows -n 100 -e 200 --schema my_schema.json
# or
docker run --rm -v "$(pwd)":/data lszeremeta/knows -n 100 -e 200 --schema /data/my_schema.json

Export to different formats

# GraphML
knows -n 50 -e 75 --schema my_schema.json -f graphml > graph.graphml
# or
knows -n 50 -e 75 --schema my_schema.json -f graphml graph.graphml
# or
docker run --rm -v "$(pwd)":/data lszeremeta/knows -n 50 -e 75 --schema /data/my_schema.json -f graphml > graph.graphml
# or
docker run --rm -v "$(pwd)":/data lszeremeta/knows -n 50 -e 75 --schema /data/my_schema.json -f graphml /data/graph.graphml

# Cypher (for Neo4j)
knows -n 50 -e 75 --schema my_schema.json -f cypher > graph.cypher
# or
knows -n 50 -e 75 --schema my_schema.json -f cypher graph.cypher
# or
docker run --rm -v "$(pwd)":/data lszeremeta/knows -n 50 -e 75 --schema /data/my_schema.json -f cypher > graph.cypher
# or
docker run --rm -v "$(pwd)":/data lszeremeta/knows -n 50 -e 75 --schema /data/my_schema.json -f cypher /data/graph.cypher

# CSV
knows -n 50 -e 75 --schema my_schema.json -f csv graph.csv
# or
docker run --rm -v "$(pwd)":/data lszeremeta/knows -n 50 -e 75 --schema /data/my_schema.json -f csv /data/graph.csv

# JSON
knows -n 50 -e 75 --schema my_schema.json -f json > graph.json
# or
knows -n 50 -e 75 --schema my_schema.json -f json graph.json
# or
docker run --rm -v "$(pwd)":/data lszeremeta/knows -n 50 -e 75 --schema /data/my_schema.json -f json > graph.json
# or
docker run --rm -v "$(pwd)":/data lszeremeta/knows -n 50 -e 75 --schema /data/my_schema.json -f json /data/graph.json

With reproducible seed

knows -n 20 -e 30 --schema my_schema.json -s 42
# or
docker run --rm -v "$(pwd)":/data lszeremeta/knows -n 20 -e 30 --schema /data/my_schema.json -s 42

Using Docker with built-in example schemas

docker run --rm lszeremeta/knows --schema /app/schema-examples/social_network_schema.json -n 50 -e 100
# or
docker run --rm lszeremeta/knows --schema /app/schema-examples/employee_schema.json -n 20 -e 30 -f cypher

Notes

  • When using --schema, the -np, -ep, and -ap options are ignored
  • Schema files must be valid JSON with .json extension
  • All property definitions are validated before graph generation
  • Invalid schemas will produce clear error messages
  • The schema format is inspired by GQL (ISO/IEC 39075) but is not a full GQL implementation