Active Graph Documentation

repository·12·Indexed 23 days ago

https://github.com/neo4jrb/activegraph

Active Graph (formerly Neo4j.rb) is an Active Model compliant Object-Graph-Mapper (OGM) for the Neo4j graph database. It provides a Ruby/JRuby wrapper featuring a high-level query builder, support for models for both nodes and relationships, transactional operations, and a migration framework. It integrates with neo4j-ruby-driver and active_attr, requiring Ruby 2.5+ and Neo4j 3.4+.

Tokens
23.3K
Snippets
78
Records
146
Agent score
78%

What's inside Active Graph

  1. Introduction to Active Graph

    12

    Active Graph is an Active Model compliant Ruby/JRuby wrapper for the Neo4j graph database. It provides a high-level interface for managing data stored in nodes and relationships.

    Key features include:

    • A high-level query building interface for complex graph traversals.
    • Integration with neo4j-ruby-driver and active_attr gems.
    • Support for transactional operations.
  2. What is ActiveGraph?

    12

    ActiveGraph (formerly known as Neo4j.rb) is an Object-Graph-Mapper (OGM) for the Neo4j graph database. It is designed for Ruby developers, following API conventions established by ActiveRecord to provide a familiar experience when working with graph data.

    Key features include:

    • Object Model: Support for Properties, Indexes/Constraints, Callbacks, Validations, and Associations.
    • First-class Relationships: Unlike many other OMs, ActiveGraph allows you to create models for both nodes and relationships.
    • Query Builder: A chainable query builder inspired by Arel.
    • Transactions: Support for transactional operations.
    • Migration Framework: A dedicated framework for managing graph schema changes.
  3. Integrating with pre-existing Neo4j databases

    12

    When using ActiveGraph with a database populated externally (e.g., via Cypher or legacy migration), ensure every Node model has a unique ID property.

    By default, ActiveGraph expects a property named uuid to be the unique identifier. If your external data uses a different property, you must either:

    1. Define and constrain that property as unique in Cypher during data loading.
    2. Override the default ID property in your ActiveGraph models.
  4. Understand ActiveGraph terminology

    12

    To use ActiveGraph effectively, you must understand how it maps Neo4j concepts to Ruby abstractions:

    Neo4j Concepts

    • Node: An entity with a distinct identity that can store arbitrary properties.
    • Label: A way to identify nodes. A single node can have multiple labels (e.g., :Person and :Teacher).
    • Relationship: A link between nodes that has a direction and can store properties.
    • Type: The single identifier for a relationship (e.g., FRIEND_OF).

    ActiveGraph Abstractions

    • Model: A Ruby class that includes either ActiveGraph::Node (for nodes) or ActiveGraph::Relationship (for relationships). Models support properties, associations, validations, and callbacks.
    • Association: A high-level abstraction defined on a Node model using has_one or has_many to define relationships to other models.
  5. How Relationship models separate logic

    12

    Relationship models are ideal for centralizing logic when multiple associations share the same relationship type but connect different node labels. This prevents 'shoehorning' complex logic into Node models.

    By using to_class :any, a single Relationship model can manage connections between various types of nodes, allowing you to centralize validations and callbacks for all connections of that type.

    class ManagedRel
      include ActiveGraph::Relationship
      after_create :update_user_stats
      validate :manageable_object
      from_class :User
      to_class :any
      type 'MANAGES'
    
      def update_user_stats
        from_node.update_stats
      end
    
      def manageable_object
        errors.add(:to_node) unless to_node.respond_to?(:managed_by)
      end
    end
  6. Define and use Node associations

    12

    You can define has_many and has_one associations on ActiveGraph::Node models to simplify querying and creating relationships. Associations can be directed :in, :out, or :both.

    Association Types

    • :in: Incoming relationships.
    • :out: Outgoing relationships.
    • :both: Both incoming and outgoing relationships.

    Configuration Options

    • type: The relationship type (e.g., :author).
    • origin: The name of the relationship on the target model that points back to this model.
    • model_class: The class of the target nodes. Can be a single class, an array of classes, or false to match any node.
    • chainable: true: For has_one associations, this returns an AssociationProxy instead of the object itself, allowing you to continue chaining even if the result is nil.
    class Post
      include ActiveGraph::Node
      has_many :in, :comments, origin: :post
      has_one :out, :author, type: :author, model_class: :Person
    end
    
    # Querying
    post.comments.to_a          # Array of comments
    comment.post                # Post object
    comment.post(chainable: true) # Association proxy object
  7. Understand property types and conversion

    12

    The type option defines the Ruby class you expect when retrieving a value, not necessarily the type stored in Neo4j.

    Supported default types:

    • String
    • Integer
    • BigDecimal
    • Date
    • Time
    • DateTime
    • Boolean (TrueClass or FalseClass)

    Key Behaviors:

    • Automatic Conversion: For types like Integer, ActiveGraph will convert string representations from the DB into the specified Ruby type. It also converts values before saving to ensure Neo4j stores them in the native format (e.g., native Ints).
    • DateTime Handling: Since Neo4j does not support Ruby's native DateTime format, ActiveGraph automatically converts DateTime objects to Integer (Unix timestamps) before saving, and converts them back to DateTime when loading.
    • Performance Tip: DateTime conversion is computationally expensive. For high-performance requirements, consider using type: Integer to store and manipulate Unix timestamps directly.
    class Post
      include ActiveGraph::Node
    
      property :score, type: Integer
      property :created_at, type: DateTime
    end
  8. Build queries using Proxy Method Chaining

    12

    Active Graph uses AssociationProxy and QueryProxy to allow building complex Cypher queries via method chaining. You can start a chain in three ways:

    1. Model.all
    2. Model.association (Class-level scope)
    3. model_object.association (Instance-level scope)

    An AssociationProxy allows for eager loading and further association calls. A QueryProxy is returned when using methods like where, allowing for filtering, sorting, and limiting before the query is executed.

    lesson.teachers.where(name: /.* smith/i, age: 34).order(:name).limit(2)
  9. Advantages of using the ActiveGraph::Core::Query DSL

    12

    The ActiveGraph::Core::Query class provides a Ruby DSL for building Cypher queries with several key benefits:

    • Method Chaining: Build parts of a query incrementally and pass the query object to other methods for further construction.
    • Automatic Parameterization: Automatically uses parameters in queries whenever possible to improve security and performance.
    • Data Integration: Allows passing data directly from Ruby sources, such as using a Hash to match keys and values.
    • Native Ruby Object Mapping: Translates native Ruby objects into Cypher syntax (e.g., translating nil to IS NULL or Ruby regular expressions to Cypher-style regular expression matches).
  10. Manage associations with unpersisted nodes

    12

    Behavior of association creation (<< or =) depends on the persistence state of the nodes:

    1. Both nodes persisted: Relationship is created immediately in the database.
    2. Calling node is unpersisted: No database changes occur until save is called on the parent node. A cascading save will then persist the child and create the relationship within a transaction.
    3. Target node is unpersisted: If you associate an unpersisted node with a persisted one (e.g., student.lessons << new_lesson), the unpersisted node is saved and the relationship is created immediately.
  11. Combine query clauses in any order

    12
    ActiveGraph's query builder is flexible; you can chain clauses like match, where, with, order, and limit in various sequences. The builder will attempt to construct a valid Cypher query based on the order of the methods called. Use .break to separate multiple MATCH clauses if they should not be part of a single pattern match.