Skip to content

Node Property Data Types

Complete reference for all supported property value types in NornicDB


Overview

NornicDB supports a rich set of data types for node and relationship properties, following Neo4j compatibility while extending support for complex nested structures. Properties are stored as map[string]any (key-value pairs) where values can be any supported type.


Supported Data Types

1. Primitive Types

String (string)

Text values of any length.

Example:

CREATE (n:Person {
  name: "Alice Johnson",
  email: "alice@example.com",
  bio: "Software engineer passionate about graph databases"
})

Use Cases: - Names, titles, descriptions - Email addresses, URLs - Text content, comments - Identifiers, codes


Integer (int, int64)

Whole numbers (positive, negative, or zero).

Example:

CREATE (n:Person {
  age: 30,
  score: 100,
  year: 2024
})

Supported Integer Types: - int (32-bit or 64-bit, platform-dependent) - int64 (64-bit signed integer) - int32 (32-bit signed integer)

Note: JSON deserialization may convert integers to float64. NornicDB accepts whole-number floats as integers for compatibility.

Use Cases: - Ages, counts, quantities - Years, timestamps - Scores, ratings - IDs, indices


Float (float64, float32)

Floating-point numbers (decimals).

Example:

CREATE (n:Product {
  price: 29.99,
  rating: 4.5,
  weight: 1.25,
  temperature: -10.5
})

Supported Float Types: - float64 (64-bit floating point, default) - float32 (32-bit floating point)

Use Cases: - Prices, measurements - Ratings, percentages - Coordinates, distances - Scientific values


Boolean (bool)

True or false values.

Example:

CREATE (n:User {
  verified: true,
  active: false,
  premium: true
})

Use Cases: - Flags, toggles - Status indicators - Feature enablement - Binary states


Null (nil)

Missing or undefined values.

Example:

CREATE (n:Person {
  name: "Alice",
  middleName: null,  // Optional field
  email: "alice@example.com"
})

Note: null is valid for any property type. Properties with null values are stored but may be omitted in queries.


2. Temporal Types

Date/Time (time.Time)

Timestamps and dates (stored as Go time.Time).

Example:

CREATE (n:Event {
  name: "Conference 2024",
  startDate: datetime("2024-06-15T09:00:00Z"),
  endDate: datetime("2024-06-17T17:00:00Z")
})

Supported Formats: - ISO 8601: "2024-06-15T09:00:00Z" - Unix timestamp: 1704067200 - Date strings: "2024-06-15"

Use Cases: - Event dates, deadlines - Created/updated timestamps - Birth dates, anniversaries - Scheduling, calendars

Note: When stored via Go API, use time.Time directly. When stored via JSON/Cypher, dates are parsed from strings.


3. Collection Types

Arrays/Lists ([]interface{}, []string, []int, []int64, []float64)

Ordered sequences of values.

Example:

CREATE (n:Person {
  name: "Alice",
  tags: ["developer", "graph-db", "go"],
  scores: [95, 87, 92],
  prices: [29.99, 49.99, 19.99],
  mixed: ["text", 42, true, 3.14]
})

Supported Array Types: - []interface{} - Mixed types (most flexible) - []string - String arrays - []int - Integer arrays - []int64 - 64-bit integer arrays - []float64 - Float arrays

Use Cases: - Tags, categories - Lists, sequences - Coordinates, vectors - Multiple values per property

Querying Arrays:

// Check if value is in array
MATCH (n:Person)
WHERE "developer" IN n.tags
RETURN n

// Access array elements
MATCH (n:Person)
RETURN n.scores[0] AS firstScore

// Array length
MATCH (n:Person)
RETURN size(n.tags) AS tagCount


Maps/Objects (map[string]interface{})

Nested key-value structures (JSON objects).

Example:

CREATE (n:Person {
  name: "Alice",
  address: {
    street: "123 Main St",
    city: "San Francisco",
    state: "CA",
    zip: "94102"
  },
  metadata: {
    created: "2024-01-15",
    version: 1,
    active: true
  }
})

Use Cases: - Nested data structures - Configuration objects - Addresses, locations - Metadata, settings

Querying Nested Objects:

// Access nested properties
MATCH (n:Person)
RETURN n.address.city AS city

// Filter by nested property
MATCH (n:Person)
WHERE n.address.state = "CA"
RETURN n

Nested Objects: Objects can be nested to any depth:

CREATE (n:Document {
  content: {
    title: "Guide",
    sections: {
      intro: {
        text: "Welcome",
        author: "Alice"
      },
      body: {
        text: "Main content",
        author: "Bob"
      }
    }
  }
})


4. Special Types

Vector Embeddings ([]float32)

Vector embeddings for semantic search (stored in NamedEmbeddings or ChunkEmbeddings, not in properties).

Note: While vectors are []float32 internally, they are not stored as regular properties. Use NamedEmbeddings or ChunkEmbeddings struct fields instead.

Example (via Cypher):

// Create node with named embedding
CALL db.index.vector.createNodeEmbedding(
  'doc-1',
  'Document',
  'content',
  'This is the document content...'
)

Example (via Go API):

node := &storage.Node{
    ID:     storage.NodeID("doc-1"),
    Labels: []string{"Document"},
    Properties: map[string]any{
        "title": "My Document",
    },
    NamedEmbeddings: map[string][]float32{
        "content": []float32{0.1, 0.2, 0.3, ...}, // 768-dim vector
    },
}

See Vector Embeddings for details.


Type Constraints (Schema Validation)

NornicDB supports property type constraints for schema enforcement:

Supported Constraint Types: - STRING - String values only - INTEGER - Integer values only - FLOAT - Float values only - BOOLEAN - Boolean values only - DATE - Date values only - DATETIME - DateTime values only

Example:

// Create type constraint
CREATE CONSTRAINT person_age_integer FOR (p:Person) REQUIRE p.age IS INTEGER

// This will fail:
CREATE (p:Person {age: "thirty"})  // ❌ Error: expected INTEGER, got string

// This will succeed:
CREATE (p:Person {age: 30})  // ✅ Valid

See Schema Constraints for details.


Type Conversion & Coercion

JSON Deserialization

When properties are loaded from JSON (HTTP API, Cypher via JSON), type conversions occur:

  • Integers: May be deserialized as float64 (JSON limitation). NornicDB accepts whole-number floats as integers.
  • Numbers: int, int64, float32, float64 are all supported.
  • Booleans: true/false only (not 1/0 or "true"/"false").

Go API Type Handling

When using the Go API directly, types are preserved:

// Types are preserved exactly
node := &storage.Node{
    Properties: map[string]any{
        "age":    int64(30),      // Preserved as int64
        "price":  float64(29.99), // Preserved as float64
        "active": true,            // Preserved as bool
    },
}

Cypher Type Handling

Cypher queries handle type conversion automatically:

// Cypher automatically converts literals
CREATE (n:Person {
  age: 30,        // Integer
  price: 29.99,   // Float
  active: true    // Boolean
})

Examples by Use Case

User Profile

CREATE (u:User {
  // Strings
  username: "alice",
  email: "alice@example.com",
  bio: "Software engineer",

  // Numbers
  age: 30,
  score: 95.5,

  // Boolean
  verified: true,
  premium: false,

  // Arrays
  tags: ["developer", "graph-db"],
  skills: ["Go", "Cypher", "GraphQL"],

  // Objects
  profile: {
    avatar: "https://example.com/avatar.jpg",
    location: "San Francisco",
    timezone: "PST"
  },

  // Date
  createdAt: datetime("2024-01-15T10:00:00Z")
})

Product Catalog

CREATE (p:Product {
  // Strings
  name: "NornicDB Pro",
  description: "Enterprise graph database",
  sku: "NOR-001",

  // Numbers
  price: 99.99,
  stock: 100,
  rating: 4.8,

  // Boolean
  available: true,
  featured: false,

  // Arrays
  categories: ["database", "graph", "enterprise"],
  images: [
    "https://example.com/img1.jpg",
    "https://example.com/img2.jpg"
  ],

  // Objects
  metadata: {
    weight: 1.5,
    dimensions: {
      width: 10,
      height: 20,
      depth: 5
    },
    manufacturer: {
      name: "NornicDB Inc",
      country: "USA"
    }
  }
})

Event/Calendar

CREATE (e:Event {
  // Strings
  title: "Graph Database Conference",
  description: "Annual conference on graph databases",
  location: "San Francisco Convention Center",

  // Numbers
  capacity: 500,
  price: 299.99,

  // Boolean
  soldOut: false,
  virtual: false,

  // Arrays
  speakers: ["Alice", "Bob", "Carol"],
  tags: ["graph-db", "conference", "networking"],

  // Objects
  schedule: {
    start: datetime("2024-06-15T09:00:00Z"),
    end: datetime("2024-06-17T17:00:00Z"),
    timezone: "PST"
  },

  // Nested objects
  venue: {
    name: "SF Convention Center",
    address: {
      street: "747 Howard St",
      city: "San Francisco",
      state: "CA",
      zip: "94103"
    }
  }
})

Best Practices

1. Use Appropriate Types

  • Use int/int64 for whole numbers (ages, counts, IDs)
  • Use float64 for decimals (prices, measurements, ratings)
  • Use string for text (names, descriptions, codes)
  • Use bool for binary states (flags, toggles)

2. Avoid Type Mixing in Arrays

While []interface{} supports mixed types, prefer homogeneous arrays for clarity:

// ✅ Good: Homogeneous array
tags: ["tag1", "tag2", "tag3"]

// ⚠️ Acceptable but less clear: Mixed array
mixed: ["text", 42, true]

Group related properties in nested objects:

// ✅ Good: Grouped related data
address: {
  street: "123 Main St",
  city: "San Francisco",
  state: "CA"
}

// ❌ Less clear: Flat structure
street: "123 Main St",
city: "San Francisco",
state: "CA"

4. Handle Null Values Explicitly

Use null for optional fields rather than empty strings or zeros:

// ✅ Good: Explicit null for optional field
CREATE (n:Person {
  name: "Alice",
  middleName: null,  // Optional
  age: 30
})

// ❌ Less clear: Using empty string
CREATE (n:Person {
  name: "Alice",
  middleName: "",  // Ambiguous: empty or missing?
  age: 30
})

5. Use Type Constraints for Schema Enforcement

Enforce types at the schema level for data integrity:

// Create constraints
CREATE CONSTRAINT person_age_integer FOR (p:Person) REQUIRE p.age IS INTEGER
CREATE CONSTRAINT person_email_string FOR (p:Person) REQUIRE p.email IS STRING

Limitations & Notes

Storage Limits

  • String length: No hard limit (limited by available memory)
  • Array size: No hard limit (limited by available memory)
  • Object depth: No hard limit (limited by available memory)
  • Property count: No hard limit per node

Type Preservation

  • JSON API: Types may be converted (integers → float64) during JSON round-trip
  • Go API: Types are preserved exactly as provided
  • Cypher: Types are inferred from literals and query context

Vector Embeddings

  • Vector embeddings are not stored as regular properties
  • Use NamedEmbeddings or ChunkEmbeddings struct fields
  • See Vector Embeddings for details

Neo4j Compatibility

  • All Neo4j property types are supported
  • NornicDB extends support for nested objects and arrays
  • Type constraints follow Neo4j syntax


Summary

Supported Types: - ✅ Primitives: string, int/int64, float64/float32, bool, null - ✅ Temporal: time.Time (dates/timestamps) - ✅ Collections: Arrays ([]interface{}, []string, []int, []float64), Maps (map[string]interface{}) - ✅ Nested: Objects can be nested to any depth - ✅ Constraints: Type constraints for schema enforcement

Not Supported as Properties: - ❌ Functions, closures - ❌ Binary data (use base64 strings) - ❌ Circular references (will cause serialization issues)

Best Practices: - Use appropriate types for clarity - Prefer homogeneous arrays - Group related data in nested objects - Use null for optional fields - Enforce types with constraints


Questions? See Complete Examples for real-world usage patterns.