Skip to main content

Database Schemas - Detailed Documentation

This document provides comprehensive details about the database schemas used in OpenGIN across MongoDB, Neo4j, and PostgreSQL.


Overview

OpenGIN uses a multi-database architecture where each database is optimized for specific data types:

DatabasePurposeData Stored
MongoDBFlexible metadataKey-value metadata pairs
Neo4jGraph relationshipsEntity nodes and relationship edges
PostgreSQLStructured attributesTime-series attribute data with schemas

MongoDB Schema

Database Information

Database Information

The Metadata Store is implemented using a document-oriented database to provide flexibility for storing unstructured or semi-structured data. This allows for dynamic metadata fields without rigid schema constraints.

Collections

1. metadata

Purpose: Store entity metadata as flexible key-value pairs

Schema (document structure):

{
"_id": "entity123", // Entity ID (Primary Key)
"metadata": { // Metadata object
"key1": "value1",
"key2": "value2",
"key3": 123,
"key4": true,
"nested": {
"subkey": "subvalue"
}
},
"created_at": ISODate("2024-01-01T00:00:00Z"), // Optional timestamp
"updated_at": ISODate("2024-01-01T00:00:00Z") // Optional timestamp
}

2. metadata_test

Purpose: Test collection for metadata (same schema as metadata)

Used during testing to isolate test data from production data.


Neo4j Schema

Database Information

The Graph Store is utilized to manage entities and their relationships. It supports both binary and HTTP protocols for interaction, enabling efficient graph traversals and complex relationship queries.

Node Types

Entity Node

Label: :Entity

Properties:

{
id: String, // Unique entity identifier (REQUIRED)
kind_major: String, // Major entity classification (REQUIRED)
kind_minor: String, // Minor entity classification (optional)
name: String, // Entity name (REQUIRED)
created: String, // ISO 8601 timestamp (REQUIRED)
terminated: String // ISO 8601 timestamp (optional, null = active)
}

Relationship Types

Dynamic Relationship System: OpenGIN uses a completely generic relationship model where relationship types are not predefined. Users can create any relationship type they need by simply providing a name field in the relationship data.

How it works:

  1. User provides relationship with name field (e.g., "reports_to", "depends_on", "manages")
  2. System dynamically creates Neo4j relationship with that type
  3. Neo4j relationship type becomes the uppercased version or exact value of the name field
  4. No schema validation or predefined list of relationship types

Relationship Structure

All relationships in Neo4j store the following properties:

Neo4j Properties (what's actually stored in the graph):

{
Id: String, // Relationship identifier (uppercase I)
Created: DateTime, // When relationship started (Neo4j datetime type)
Terminated: DateTime // When relationship ended (Neo4j datetime type, null = active)
}

Important: The name field from the API/Protobuf becomes the relationship TYPE in Neo4j, not a property. It appears in the Cypher syntax as [:relationshipType].

Note: The direction field is not stored in Neo4j - it's determined by the direction of the arrow in the graph (→ for outgoing, ← for incoming).

Relationship Types: Relationship types are completely dynamic and user-defined. The system does not enforce any predefined relationship types. When creating a relationship, the name field from the Relationship protobuf message becomes the Neo4j relationship type.

Examples from tests and usage:

  • reports_to: Organizational hierarchy (from E2E tests)
  • depends_on: Package dependencies (from unit tests)
  • Any other name: Users can define any relationship type they need

PostgreSQL Schema

Database Information

Database Information

The Attribute Store is built on a relational database system to manage structured, time-series attribute data. It ensures data integrity and supports complex querying capabilities through defined schemas.

Core Tables

1. Attribute Schema

This table defines the structure of attributes for different entity kinds. It acts as a registry, specifying properties such as data types and storage strategies (e.g., scalar, list, map), ensuring consistent data handling for specific entity classifications.

2. Entity Attributes

This table serves as a mapping layer, linking unique entity identifiers to the specific attribute definitions stored here. It allows the system to associate concrete data values with the defined structure for any given entity.

Dynamic Attribute Tables

To optimize performance and organize data efficiently, the system automatically creates dedicated tables for attributes based on their entity classification. This approach ensures that attribute data is stored in a structured manner, allowing for faster retrieval and better data management compared to a single monolithic table.

Data Integrity

No Distributed Transactions: Currently, OpenGIN doesn't use distributed transactions. Each database operation is independent.

Eventual Consistency: System relies on application-level consistency:

  • Entity ID is the common key across all databases
  • Core API orchestrates all operations
  • Errors are logged but don't rollback previous successful operations

Future Enhancement: Implement distributed transactions.


Backup and Restore

Metadata Store Backup

mongodump --uri="mongodb://admin:<your_password>@mongodb:27017/opengin?authSource=admin" \
--out=/backup/mongodb/

Neo4j Backup

neo4j-admin dump --database=neo4j --to=/backup/neo4j/neo4j.dump

PostgreSQL Backup

pg_dump -h postgres -U postgres -d opengin -F tar -f /backup/postgres/opengin.tar

See Backup Integration Guide for complete backup/restore workflow.

Reference