Skip to content

jgaskins/neo4j.cr

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

neo4j.cr

Neo4j connector for Crystal, supporting the Bolt protocol and routing queries to appropriate nodes in your Neo4j cluster.

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

  • type : (Neo4j::Success | Neo4j::Ignored)
    • If you get an Ignored result, it probably means an error occurred. Call connection#reset to get it back to working order.
    • If a query results in a Neo4j::Failure, an exception is raised rather than wrapping it in a Result.
  • data : Array(Array(Neo4j::Type))
    • This is the list of result values. For example, if you RETURN a, b, c from your query, then this will be an array of [a, b, c].

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.

  • id : Int32: the node's internal id
    • WARNING: Do not store this id anywhere. These ids can be reused by the database. If you need an application-level unique id, store a UUID on the node. It is useful in querying nodes connected to this one when you already have it in memory, but not beyond that.
  • labels : Array(String): the labels stored on your node
  • properties : Hash(String, Neo4j::Type): the properties assigned to this node

Neo4j::Relationship

  • id: Int32: the relationship's internal id
  • type : String: the type of relationship
  • start : Int32: the internal id for the node on the starting end of this relationship
  • end : Int32: the internal id of the node this relationship points to
  • properties : Hash(String, Neo4j::Type): the properties assigned to this 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

  • jgaskins Jamie Gaskins - creator, maintainer

About

Pure-Crystal implementation of Neo4j's Bolt protocol

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published