neo4j.cr

Join the chat at https://gitter.im/jgaskins/neo4j.cr Check out the build on Travis CI

Crystal implementation of a Neo4j driver using the Bolt protocol.

Installation

Add this to your application's shard.yml:

dependencies:
  neo4j:
    github: jgaskins/neo4j.cr

Usage

First you need to set up a connection:

require "neo4j"

neo4j_uri = URI.parse("bolt://neo4j:password@localhost:7687")

# The `ssl` option defaults to `true` so you don't accidentally send the
# password to your production DB in cleartext.
driver = Neo4j.connect(neo4j_uri, ssl: false)

This will return a cluster driver or a direct driver depending on whether you provided a neo4j:// or bolt:// URI, respectively. neo4j:// can also be specified as bolt+routing://. Both drivers expose the same interface, but the cluster driver will route queries to a different server based on whether you specify that the query is a read or write query.

struct Person
  include Neo4j::Serializable::Node

  getter id: UUID
  getter name: String
  getter email: String
end

driver.session do |session|
  session.read_transaction do |read|
    query = <<-CYPHER
      MATCH (person:Person { name: $name })
      RETURN person
    CYPHER

    read.exec_cast(query, {Person}, name: "Jamie") do |(person)|
      pp person
    end
  end

  session.write_transaction do |write|
    write.execute <<-CYPHER, name: "Jamie"
      MATCH (person:Person { name: $name })
      SET person.login_count = person.login_count + 1
    CYPHER
  end
end

Neo4j::Result

The Result object itself is an Enumerable. Calling Result#each will iterate over the data for you.

Neo4j::Node

These have a 1:1 mapping to nodes in your graph.

Neo4j::Relationship

Neo4j::Value

Represents any data type that can be stored in a Neo4j database and communicated via the Bolt protocol. It's a shorthand for this union type:

Nil |
Bool |
String |
Int8 |
Int16 |
Int32 |
Int64 |
Float64 |
Time |
Neo4j::Point2D |
Neo4j::Point3D |
Neo4j::LatLng |
Array(Neo4j::Value) |
Hash(String, Neo4j::Value) |
Neo4j::Node |
Neo4j::Relationship |
Neo4j::UnboundRelationship |
Neo4j::Path

Mapping to Domain Objects

Similar to JSON.mapping in the Crystal standard library, you can map nodes and relationships to domain objects. For example:

require "uuid"

class User
  include Neo4j::Serializable::Node

  getter uuid : UUID
  getter email : String
  getter name : String
  getter registered_at : Time
end

class Product
  include Neo4j::Serializable::Node

  getter uuid : UUID
  getter name : String
  getter description : String
  getter price : Int32
  getter created_at : Time
end

class CartItem
  include Neo4j::Serializable::Relationship

  getter quantity : Int32
  getter price : Int32
end

Acknowledgements/Credits

The implementation of the wire protocol is heavily based on the MessagePack shard to understand how to serialize and deserialize a binary protocol in Crystal.

Contributing

  1. Fork it ( https://github.com/jgaskins/neo4j.cr/fork )
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create a new Pull Request

Contributors